Что нового

Переход с клетки на клетку в обпределённой области на примере сапёра

martiniFresh

Новичок
Сообщения
10
Репутация
1
Здравствуйте.
Подскажите пожалуйста ещё вот что:
Как реализовать такую идею - Задаётся определённая область координат с 4 переменными x1 и y1, x2 и y2 далее (бот ориентирован на игру сапёр) бот щёлкает по очереди по клеткам минного поля с лева на право при достижение границ заданного поля бот переходит на строку ниже и щёлкает по клеткам уже с права на лево. Если идея понятна, прошу помочь. А если нет, то спрашивайте, уточню.
Заранее спасибо.
 

DeLeTeSHift

Знающий
Сообщения
46
Репутация
9
это пожалуй не совсем то что ты спрашивал, и "тыкает" он всегда слева на право, но в общем вот:
Код:
Func Miner_Bot($x_area, $y_area) ; указать размеры поля в клеточках
   
$hwnd  = WinWait("[CLASS:Minesweeper]", "", 5)
If $hwnd == 0 Then
   Run("C:\Program Files\Microsoft Games\Minesweeper\MineSweeper.exe")
EndIf
WinActivate("[CLASS:Minesweeper]")
WinWaitActive("[CLASS:Minesweeper]")

AutoItSetOption("PixelCoordMode", 2)
AutoItSetOption("MouseCoordMode", 2)

For $y = 40 To $y_area*20 Step 20
   For $x =40 To $x_area*20 Step 20
      MouseClick("", $x, $y) 	  
   Next
Next
EndFunc

Но это функцию не получится переделать под умного бота, расскажи поподробнее про концепцию определения мин, тогда я смогу хоть чем то помочь
 
Автор
M

martiniFresh

Новичок
Сообщения
10
Репутация
1
Про концепцию определения мин через оффсеты если это можно тут применить я только слышала и пока ещё далека от этого. Я так поняла, что это чтение мин из памяти. Если не сложно кому то то можете объяснить и помочь разобраться с работой в памяти программ посредством ЛС. Но это лирическое отступление. ;)
А если ближе к делу, то у меня мины определятся будут просто. Бот набирает в окне сапёра xyzzy+Shift и по условию равен ли пиксель 0х0 белому цвету->щелчёк по клетке если нет, пропуск. И всё это дело в цикл который будет завершаться когда бот достигнет конца поля. А с памятью то наверно было бы интересней... :-[ ;)
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Таак...
Девочки пьют мартини, а мы давайте подумаем над концепцией.
Начальный вариант.

Структуры данных.
imho, двумерный массив целых чисел размера игрового поля.
В клетках:
0-8 - открытая клетка, количество мин в соседних клетках,
10 - неоткрытая свободная клетка,
11 - неоткрытая клетка отмеченная как мина.

Алгоритм.
Шаг 1. Сканируем поле и заполняем массив клеток поля.
Шаг 2. Перебираем открытые клетки игрового поля. Если возле клетки количество свободных клеток и мин равно её значению, то все соседние свободные клетки отмечаем как мины.
Шаг 3. Перебираем открытые клетки игрового поля. Если возле клетки количество мин равно её значению, то все соседние свободные клетки открываем.
Шаг 4. Если прошли всё поле и не открыли ни одной клетки то рандомно открываем закрытую свободную клетку поля. Если не подорвались, то идём на Шаг 1.
 
Автор
M

martiniFresh

Новичок
Сообщения
10
Репутация
1
:smile: По сути да, всё верно по логике. Но как определяется то сколько байт в ячейке памяти клетки? И что будет если нарваться на мину всё же или это исключено? И как всё же организовать этот алгоритм с памятью? В моём задуманном случае то вроде логически просто всё. Есть байт определённого цвета и по условию что этот байт нужного цвета, происходит ряд действий.
Вот алгоритм моей задумки:
1. Либо пользователь определяет размер поля, либо сами статично задаём в боте.
2. бот становится на первую клетку поля и проверяет условие - равен ли байт в координатах 0х0 белому цвету, если да то щёлкает по клетке поля и переходит на следующую клетку в право. Если нет, то просто переходит на клетку вправо и проверяет эту клетку.

По сути просто но во первых я только начала Autoit заниматься, а во вторых с памятью может было бы интересней.)
 

Whited

Знающий
Сообщения
79
Репутация
10
C2H5OH [?]
Алгоритм.Шаг 1. Сканируем поле и заполняем массив клеток поля.


Уже который день бьюсь над скоростью этого этапа, получается сек 2-3 это очень много, массив 8х8 есть варианты увеличить скорость?

Делаю так:

Код:
for $i = 0 to 7
	  for $j = 0 to 7
			ToolTip($i & " " & $j & " " & $a & "=Flag=" & $Flag,200,200)
        $massiv[$i][$j] = "0x"& Hex(PixelGetColor($X+$glick,$Y+$glick),6)
    $X = $X+$step
    Next
    $X = $PoleX
	$Y = $Y+$step
 Next
$Y = $PoleY


Ну долго , что ппц.
 
Автор
M

martiniFresh

Новичок
Сообщения
10
Репутация
1
Если я правильно поняла, то эта часть же по нескольку проходит полный круг сканирования и даже те которые уже проходили проверку. Верно? Или я ошиблась? а нельзя ещё один массив выделить для тех байт которые уже проверены?
 

Whited

Знающий
Сообщения
79
Репутация
10
martiniFresh [?]
Если я правильно поняла, то эта часть же по нескольку проходит полный круг сканирования и даже те которые уже проходили проверку. Верно? Или я ошиблась? а нельзя ещё один массив выделить для тех байт которые уже проверены?

Почему? в i -строки, в j- столбцы.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
martiniFresh,
оно тебе надо лезть в память?

Whited,
откуда поле 8х8 ? Я смог уменьшить только до 9х9.

Вот реализация "в лоб" описанного алгоритма.
Код:
#cs
Бот для игры Сапёр.
Версия 1.0
#ce

Global $poleSizeX = 9, $poleSizeY = 9	; размер поля
Global $MaxMineNumber = 10, $MinesFound	; количество найденных мин
Global $OpenFlag
Dim $pole[$poleSizeX][$poleSizeY]

If Not WinExists("Сапер") Then MsgBox(4096, "Error", "Сапер не запущен")
WinActivate("Сапер")
Sleep(1000)
Opt("PixelCoordMode", 0)
Opt("MouseCoordMode", 0)

While Not MineSwepperExplosion() ;пока не подорвался
	MineSwepperScan()	; Шаг 1
	MineSwepperCheckCells()	; Шаг 2
	$MinesFound = MineSwepperCalculateMines() ; посчитать найденные мины
	If $MinesFound = $MaxMineNumber Then	; если все мины найдены
		MineSwepperOpenAllClearCells()		; то открываем все оставшиеся клетки
		MsgBox(0,"Бот Сапёр","Все мины найдены")
		Exit
	EndIf
	MineSwepperOpenCells()		; Шаг 3
	If Not $OpenFlag Then MineSwepperOpenRandomCell()	; Шаг 4
WEnd

MsgBox(0,"Бот Сапёр","Подорвался")

Func MineSwepperScan()
	For $i = 0 To $poleSizeX-1
		For $j = 0 To $poleSizeY-1
			If PixelGetColor(15+16*$i,105+16*$j) = 0xFFFFFF Then
				If PixelGetColor(22+16*$i,108+16*$j) = 0xFF0000 Then
					$pole[$i][$j] = 11
				Else
					$pole[$i][$j] = 10
				EndIf
			Else
				$color = PixelGetColor(22+16*$i,108+16*$j)
				Switch $color
					Case 0xC0C0C0
						$pole[$i][$j] = 0
					Case 0x0000FF
						$pole[$i][$j] = 1
					Case 0x008000
						$pole[$i][$j] = 2
					Case 0xFF0000
						$pole[$i][$j] = 3
					Case 0x000080
						$pole[$i][$j] = 4
					Case 0x800000
						$pole[$i][$j] = 5
					Case Else
						MsgBox(4096, "Error", "Неизвестное количество мин в поле "&$i&"x"&$j)
				EndSwitch
			EndIf
		Next
	Next
EndFunc

Func MineSwepperCheckCells()
	Local $m
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] >= 10 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							MouseMove(22+16*($x+$i),110+16*($y+$j),0)
							Sleep(500)
							MouseClick("Right", 22+16*($x+$i),110+16*($y+$j))
							$pole[$x+$i][$y+$j] = 11
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MineSwepperOpenCells()
	Local $m
	$OpenFlag = False
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 11 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							MouseMove(22+16*($x+$i),110+16*($y+$j),0)
							Sleep(500)
							MouseClick("Left", 22+16*($x+$i),110+16*($y+$j))
							$OpenFlag = True
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MineSwepperCalculateMines()
	Local $m = 0
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 11  Then $m += 1
		Next
	Next
	Return $m
EndFunc

Func MineSwepperOpenRandomCell()
	While 1
		$x = Random(0, $poleSizeX-1, 1)
		$y = Random(0, $poleSizeY-1, 1)
		If $pole[$x][$y] = 10 Then
			MouseMove(22+16*($x),110+16*($y),0)
			Sleep(500)
			MouseClick("Left", 22+16*$x,110+16*$y)
			Return
		EndIf
	WEnd
EndFunc

Func MineSwepperOpenAllClearCells()
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 10 Then
				MouseMove(22+16*($x),110+16*($y),0)
				Sleep(500)
				MouseClick("Left", 22+16*$x,110+16*$y)
			EndIf
		Next
	Next
EndFunc

Func MineSwepperExplosion()
	If PixelGetColor(19+16*Floor($poleSizeX/2),81) = 0x000000 Then
		Return True
	Else
		Return False
	EndIf
EndFunc

Понятно что он не совершенен, его можно улучшить, оптимизировать, ускорить. Дерзайте.
Меня скорость работы вполне устраивает.
Конечно, неплохо бы бы найти ситуации когда рядом с открытой клеткой 6, 7 и 8 мин, а то мне на скорую руку попались только до 5.
Хотел добавить комментарии к коду, но даже не знаю что тут нужно комментировать.
Если есть вопросы, задавайте в этой теме.
 

DeLeTeSHift

Знающий
Сообщения
46
Репутация
9
C2H5OH, у меня выбивает кучу ошибок про неизвестное количество мины, потом тыкает на уголки открытых клеток, если такие есть, а потом взрывается, жмёт выход и тыкает что то в SciTE, видимо у меня разрешение не то
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
DeLeTeSHift,
У меня сапёр выглядит вот так
ac89fdd3d5cc.jpg


А у тебя?
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Whited,
не могу ничего сказать по поводу быстродействия твоего скрипта, так как не знаю что ты делаешь в этом цикле.

На Шаге 1 я смотрю вот этот пиксель в каждой клетке
9188efbcdd65.jpg
И по цвету этого пиксеселя определяю какая там цифра.

Поставил в скрипт замер времени
Код:
$timer = TimerInit()
	MineSwepperScan()	; Шаг 1
	$time1 = TimerDiff($timer)
	ConsoleWrite("time = "&$time1&@CR)


Вот что получил в консоли (для уровня ингры "Новичок" - поле 9х9)
Код:
time = 7.11738503077905
time = 4.08320051850165
time = 4.61846407853512
time = 7.16767075145025
time = 5.79431184689674
time = 3.27639406684369
time = 2.10194312405627
time = 2.10585423566403

По-моему время 2-7 мс вполне нормально для функции сканирования.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Чет на меня вдохновение нашло...
Код:
#cs
Бот для игры Сапёр.
Версия 2.1
#ce

;Global $poleSizeX = 9, $poleSizeY = 9, $MaxMineNumber = 10	; Новичок
;Global $poleSizeX = 16, $poleSizeY = 16, $MaxMineNumber = 40	; Любитель
Global $poleSizeX = 30, $poleSizeY = 16, $MaxMineNumber = 99	; Профи

Global $MinesFound	; количество найденных мин
Global $OpenFlag
Dim $pole[$poleSizeX][$poleSizeY]

If Not WinExists("Сапер") Then MsgBox(4096, "Error", "Сапер не запущен")
WinActivate("Сапер")
Sleep(1000)
Opt("PixelCoordMode", 0)
Opt("MouseCoordMode", 0)

While Not MineSwepperExplosion() ;пока не подорвался
	MineSwepperScan()	; Шаг 1
	MineSwepperCheckCells()	; Шаг 2
	$MinesFound = MineSwepperCalculateMines() ; посчитать найденные мины
	If $MinesFound = $MaxMineNumber Then	; если все мины найдены
		MineSwepperOpenAllClearCells()		; то открываем все оставшиеся клетки
		MsgBox(0,"Бот Сапёр","Все мины найдены")
		Exit
	EndIf
	MineSwepperOpenCells()		; Шаг 3

	If Not $OpenFlag Then		; Шаг 3.5
		For $i = 0 To $poleSizeX-1
			For $j = 0 To $poleSizeY-1
				If MineSwepperAdvansedOpenCell($Pole, $i, $j) Then
					$OpenFlag = True
					ExitLoop 2
				EndIf
			Next
		Next
	EndIf

	If Not $OpenFlag Then MineSwepperOpenRandomCell()	; Шаг 4
WEnd

MsgBox(0,"Бот Сапёр","Подорвался")

Func MineSwepperScan()
	For $i = 0 To $poleSizeX-1
		For $j = 0 To $poleSizeY-1
			If PixelGetColor(15+16*$i,105+16*$j) = 0xFFFFFF Then
				If PixelGetColor(22+16*$i,108+16*$j) = 0xFF0000 Then
					$pole[$i][$j] = 11
				Else
					$pole[$i][$j] = 10
				EndIf
			Else
				$color = PixelGetColor(22+16*$i,108+16*$j)
				Switch $color
					Case 0xC0C0C0
						$pole[$i][$j] = 0
					Case 0x0000FF
						$pole[$i][$j] = 1
					Case 0x008000
						$pole[$i][$j] = 2
					Case 0xFF0000
						$pole[$i][$j] = 3
					Case 0x000080
						$pole[$i][$j] = 4
					Case 0x800000
						$pole[$i][$j] = 5
					Case 0x008080
						$pole[$i][$j] = 6
					Case Else
						MsgBox(4096, "Error", "Неизвестное количество мин в поле "&$i&"x"&$j)
				EndSwitch
			EndIf
		Next
	Next
EndFunc

Func MineSwepperCheckCells()
	Local $m
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] >= 10 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							MouseMove(22+16*($x+$i),110+16*($y+$j),0)
							Sleep(100)
							MouseClick("Right", 22+16*($x+$i),110+16*($y+$j))
							$pole[$x+$i][$y+$j] = 11
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MineSwepperOpenCells()
	Local $m
	$OpenFlag = False
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 11 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
								MouseMove(22+16*($x+$i),110+16*($y+$j),0)
								Sleep(100)
								MouseClick("Left", 22+16*($x+$i),110+16*($y+$j))
								$OpenFlag = True
							EndIf
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MineSwepperCalculateMines()
	Local $m = 0
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 11  Then $m += 1
		Next
	Next
	Return $m
EndFunc

Func MineSwepperOpenRandomCell()
	ConsoleWrite("рандомный клик "&@CR)
	While 1
		$x = Random(0, $poleSizeX-1, 1)
		$y = Random(0, $poleSizeY-1, 1)
		If $pole[$x][$y] = 10 Then
			MouseMove(22+16*($x),110+16*($y),0)
			Sleep(100)
			MouseClick("Left", 22+16*$x,110+16*$y)
			Return
		EndIf
	WEnd
EndFunc

Func MineSwepperOpenAllClearCells()
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 10 Then
				MouseMove(22+16*($x),110+16*($y),0)
				Sleep(100)
				MouseClick("Left", 22+16*$x,110+16*$y)
			EndIf
		Next
	Next
EndFunc

Func MineSwepperExplosion()
	If PixelGetColor(19+16*Floor($poleSizeX/2),81) = 0x000000 Then
		Return True
	Else
		Return False
	EndIf
EndFunc

Func MineSwepperAdvansedOpenCell($aPole, $cellX, $cellY)
	;ConsoleWrite("вокруг "&$cellX&","&$cellY&@CR)
	If $aPole[$cellX][$cellY] = 0  Then Return False
	If $aPole[$cellX][$cellY] > 8  Then Return False

	Local $sum10 = 0, $sum11 = 0
	For $i = -1 To 1
		If $cellX+$i < 0 Then ContinueLoop
		If $cellX+$i > $poleSizeX-1 Then ContinueLoop
		For $j = -1 To 1
			If $cellY+$j < 0 Then ContinueLoop
			If $cellY+$j > $poleSizeY-1 Then ContinueLoop
			If $aPole[$cellX+$i][$cellY+$j] = 11 Then $sum11 += 1
			If $aPole[$cellX+$i][$cellY+$j] = 10 Then $sum10 += 1
		Next
	Next

	If $aPole[$cellX][$cellY] <> $sum11+1 Then Return False
	If $sum10 = 0 Then Return False

	For $i = -1 To 1
		If $cellX+$i < 0 Then ContinueLoop
		If $cellX+$i > $poleSizeX-1 Then ContinueLoop
		For $j = -1 To 1
			If $cellY+$j < 0 Then ContinueLoop
			If $cellY+$j > $poleSizeY-1 Then ContinueLoop
			If $aPole[$cellX+$i][$cellY+$j] = 10 Then $aPole[$cellX+$i][$cellY+$j] = 1 / $sum10
		Next
	Next

	;_ArrayDisplay($aPole)

	Local $m, $s
	For $x = $cellX-2 To $cellX+2
		If $x < 0 Then ContinueLoop
		If $x > $poleSizeX-1 Then ContinueLoop
		For $y = $cellY-2 To $cellY+2
			If $y < 0 Then ContinueLoop
			If $y > $poleSizeY-1 Then ContinueLoop

			If ($aPole[$x][$y] < 10) And ($aPole[$x][$y] >= 1) Then
				$m = 0
				$s = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $aPole[$x+$i][$y+$j] = 11 Then $m += 1
						If $aPole[$x+$i][$y+$j] = 10 Then $s += 1
						If $aPole[$x+$i][$y+$j] < 1 Then $m += $aPole[$x+$i][$y+$j]
					Next
				Next

				ConsoleWrite("вокруг ("&$aPole[$cellX][$cellY]&")"&$cellX&","&$cellY&" сейчас "&$x&","&$y&" сумма "&$aPole[$x][$y]&" из "&$m&@CR)

				If $aPole[$x][$y] = $m  Then
					;_ArrayDisplay($aPole)
					For $i = -1 To 1
						If $x+$i < 0 Then ContinueLoop
						If $x+$i > $poleSizeX-1 Then ContinueLoop
						For $j = -1 To 1
							If $y+$j < 0 Then ContinueLoop
							If $y+$j > $poleSizeY-1 Then ContinueLoop
							If $aPole[$x+$i][$y+$j] = 10 Then
								If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
									MouseMove(22+16*($x+$i),110+16*($y+$j),0)
									Sleep(100)
									MouseClick("Left", 22+16*($x+$i),110+16*($y+$j))
									Return True
								EndIf
							EndIf
						Next
					Next
				EndIf

				If $aPole[$x][$y] = ($s+$m)  Then
					For $i = -1 To 1
						If $x+$i < 0 Then ContinueLoop
						If $x+$i > $poleSizeX-1 Then ContinueLoop
						For $j = -1 To 1
							If $y+$j < 0 Then ContinueLoop
							If $y+$j > $poleSizeY-1 Then ContinueLoop
							If $aPole[$x+$i][$y+$j] = 10 Then
								If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
									MouseMove(22+16*($x+$i),110+16*($y+$j),0)
									Sleep(100)
									MouseClick("Right", 22+16*($x+$i),110+16*($y+$j))
									Return True
								EndIf
							EndIf
						Next
					Next
				EndIf

			EndIf
		Next
	Next
	Return False
EndFunc

Ну и
890baddb46d4.jpg


Хотя на уровне Профи выигрывает далеко не всегда, потому как часто возникают ситуации когда нужно делать рандомный клик в закрытую область.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Блин, перставил я систему и обнаружил такую неприятность...
Я ж в параметрах монитора всегда уменьшаю яркость (такая привычка, выработанная годами). Поэтому цвета, которые я использовал в скрипте, не совпадают с цветами на других компах.

Добавил в скрипт "обучение".
Несколько первых запусков нужно будет ввести какая цифра стоит в указанной клетке. :smile:
Код:
#cs
Бот для игры Сапёр.
Версия 6
#ce

HotKeySet("!{F11}", "Terminate")	; Alt + F11
Func Terminate()
	ConsoleWrite("остановлено"&@CR&"-----------"&@CR)
    Exit 0
EndFunc

HotKeySet("{F11}", "Minesweeper")

Global $poleSizeX, $poleSizeY, $MaxMineNumber
Global $MinesFound	; количество найденных мин
Global $OpenFlag
Global $pole[1][1]
Global $tmpCellColors[11]
Global $CellColors[11] = [0xC0C0C0, 0x0000FF, 0x008000, 0xFF0000, 0x000080, 0x800000, 0x008080, 0x000000, 0xFFFFFF, 0xFFFFFF, 0xFF0000]
; принятые значения полей
; 0 - открытое поле, рядом 0 мин
; 1 - открытое поле, рядом 1 мина
; 2 - открытое поле, рядом 2 мины
; 3 - открытое поле, рядом 3 мины
; 4 - открытое поле, рядом 4 мины
; 5 - открытое поле, рядом 5 мин
; 6 - открытое поле, рядом 6 мин
; 7 - открытое поле, рядом 7 мин
; 8 - мифичесоке открытое поле, рядом 8 мин
; 10 - неоткрытое необозначенное поле
; 11 - мина

#include <file.au3>

If _FileReadToArray("CellColors.dat", $tmpCellColors) Then
	For $i=0 To 10
		$CellColors[$i] = Number($tmpCellColors[$i+1])
	Next
EndIf

While 1
	Sleep(10000)
WEnd

Func Minesweeper()
	If Not WinExists("Сапер") Then MsgBox(4096, "Error", "Сапер не запущен")
	WinActivate("Сапер")
	Sleep(1000)
	$size = WinGetClientSize("[active]")
	Select
		Case $size[0]=164 And $size[1]=207	; Новичок
			$poleSizeX = 9
			$poleSizeY = 9
			$MaxMineNumber = 10
		Case $size[0]=276 And $size[1]=319	; Любитель
			$poleSizeX = 16
			$poleSizeY = 16
			$MaxMineNumber = 40
		Case $size[0]=500 And $size[1]=319	; Профи
			$poleSizeX = 30
			$poleSizeY = 16
			$MaxMineNumber = 99
		Case Else
			Send("{F10}")
			Send("{DOWN 5}")
			Send("{ENTER}")
			$oText = WinGetText("Специальное поле")
			Send("{ESC}")
			ConsoleWrite($oText)
			$aParam = StringRegExp($oText,".*?(\d+).*?",3)
			$poleSizeX = $aParam[0]
			$poleSizeY = $aParam[1]
			$MaxMineNumber = $aParam[2]
	EndSelect

	ReDim $pole[$poleSizeX][$poleSizeY]

	Opt("PixelCoordMode", 0)
	Opt("MouseCoordMode", 0)

If PixelGetColor(22+16*Floor($poleSizeX/2),77) = 0x000000 Or MinesweeperExplosion() Then
	MouseMove(19+16*Floor($poleSizeX/2),81,0)
	Sleep(100)
	MouseClick("Left", 19+16*Floor($poleSizeX/2),81)
EndIf

	While 1
		If MinesweeperExplosion() Then Return	;если подорвался
		MinesweeperScan()	; Шаг 1
		MinesweeperCheckCells()	; Шаг 2
		$MinesFound = MinesweeperCalculateMines() ; посчитать найденные мины
		If $MinesFound = $MaxMineNumber Then	; если все мины найдены
			MinesweeperOpenAllClearCells()		; то открываем все оставшиеся клетки
			Return
		EndIf
		MinesweeperOpenCells()		; Шаг 3

		If Not $OpenFlag Then		; Шаг 3.5
			For $i = 0 To $poleSizeX-1
				For $j = 0 To $poleSizeY-1
					If MinesweeperAdvansedOpenCell($Pole, $i, $j) Then
						$OpenFlag = True
						ExitLoop 2
					EndIf
				Next
			Next
		EndIf

		If Not $OpenFlag Then MinesweeperOpenRandomCell()	; Шаг 4
	WEnd
EndFunc

Func MinesweeperScan()
	Local $x
	For $i = 0 To $poleSizeX-1
		For $j = 0 To $poleSizeY-1
			If PixelGetColor(15+16*$i,105+16*$j) = 0xFFFFFF Then
				If PixelGetColor(22+16*$i,108+16*$j) = $CellColors[10] Then
					$pole[$i][$j] = 11
				Else
					$pole[$i][$j] = 10
				EndIf
			Else
				$color = PixelGetColor(22+16*$i,108+16*$j)
				Switch $color
					Case $CellColors[0]
						$pole[$i][$j] = 0
					Case $CellColors[1]
						$pole[$i][$j] = 1
					Case $CellColors[2]
						$pole[$i][$j] = 2
					Case $CellColors[3]
						$pole[$i][$j] = 3
					Case $CellColors[4]
						$pole[$i][$j] = 4
					Case $CellColors[5]
						$pole[$i][$j] = 5
					Case $CellColors[6]
						$pole[$i][$j] = 6
					Case $CellColors[7]
						$pole[$i][$j] = 7
					Case $CellColors[8]
						$pole[$i][$j] = 8
					Case Else
						MouseMove(23+16*$i,109+16*$j,0)
						$x = InputBox("error", "Неизвестное количество мин в поле "&$i&"x"&$j&@CR&"цвет 0x"&Hex($color,6)&@CR&"введите количество мин, которое изображено в этой клетке"&@CR&"0 - открытая пустая клетка"&@CR&"9 - неоткрытое поле")
						$CellColors[$x] = $color
						$pole[$i][$j] = $x
						if $x>8 Then $pole[$i][$j] += 1 ; для констант обозначающих пустое поле и мину
						$file = FileOpen("CellColors.dat",2)
						For $t=0 To 10
							FileWriteLine($file, "0x"&Hex($CellColors[$t],6))
						Next
						FileClose($file)
				EndSwitch
			EndIf
		Next
	Next
EndFunc

Func MinesweeperCheckCells()
	Local $m
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] >= 10 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							MouseMove(22+16*($x+$i),110+16*($y+$j),0)
							Sleep(100)
							MouseClick("Right", 22+16*($x+$i),110+16*($y+$j))
							$pole[$x+$i][$y+$j] = 11
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MinesweeperOpenCells()
	Local $m
	$OpenFlag = False
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] < 10  Then
				$m = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 11 Then $m += 1
					Next
				Next
			EndIf
			If $pole[$x][$y] = $m  Then
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $pole[$x+$i][$y+$j] = 10 Then
							If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
								MouseMove(22+16*($x+$i),110+16*($y+$j),0)
								Sleep(100)
								MouseClick("Left", 22+16*($x+$i),110+16*($y+$j))
								$OpenFlag = True
							EndIf
						EndIf
					Next
				Next
			EndIf
		Next
	Next
EndFunc

Func MinesweeperCalculateMines()
	Local $m = 0
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 11  Then $m += 1
		Next
	Next
	Return $m
EndFunc

Func MinesweeperOpenRandomCell()
	While 1
		$x = Random(0, $poleSizeX-1, 1)
		$y = Random(0, $poleSizeY-1, 1)
		If $pole[$x][$y] = 10 Then
			ConsoleWrite("рандомный клик "&$x&","&$y&@CR)
			MouseMove(22+16*($x),110+16*($y),0)
			Sleep(100)
			MouseClick("Left", 22+16*$x,110+16*$y)
			Return
		EndIf
	WEnd
EndFunc

Func MinesweeperOpenAllClearCells()
	For $x = 0 To $poleSizeX-1
		For $y = 0 To $poleSizeY-1
			If $pole[$x][$y] = 10 Then
				MouseMove(22+16*($x),110+16*($y),0)
				Sleep(100)
				MouseClick("Left", 22+16*$x,110+16*$y)
			EndIf
		Next
	Next
EndFunc

Func MinesweeperExplosion()
	If PixelGetColor(19+16*Floor($poleSizeX/2),81) = 0x000000 Then
		Return True
	Else
		Return False
	EndIf
EndFunc

Func MinesweeperAdvansedOpenCell($aPole, $cellX, $cellY)
	;ConsoleWrite("вокруг "&$cellX&","&$cellY&@CR)
	If $aPole[$cellX][$cellY] = 0  Then Return False
	If $aPole[$cellX][$cellY] > 8  Then Return False

	Local $sum10 = 0, $sum11 = 0
	For $i = -1 To 1
		If $cellX+$i < 0 Then ContinueLoop
		If $cellX+$i > $poleSizeX-1 Then ContinueLoop
		For $j = -1 To 1
			If $cellY+$j < 0 Then ContinueLoop
			If $cellY+$j > $poleSizeY-1 Then ContinueLoop
			If $aPole[$cellX+$i][$cellY+$j] = 11 Then $sum11 += 1
			If $aPole[$cellX+$i][$cellY+$j] = 10 Then $sum10 += 1
		Next
	Next

	If $aPole[$cellX][$cellY] <> $sum11+1 Then Return False
	If $sum10 = 0 Then Return False

	For $i = -1 To 1
		If $cellX+$i < 0 Then ContinueLoop
		If $cellX+$i > $poleSizeX-1 Then ContinueLoop
		For $j = -1 To 1
			If $cellY+$j < 0 Then ContinueLoop
			If $cellY+$j > $poleSizeY-1 Then ContinueLoop
			If $aPole[$cellX+$i][$cellY+$j] = 10 Then $aPole[$cellX+$i][$cellY+$j] = 1 / $sum10
		Next
	Next

	Local $m, $s
	For $x = $cellX-2 To $cellX+2
		If $x < 0 Then ContinueLoop
		If $x > $poleSizeX-1 Then ContinueLoop
		For $y = $cellY-2 To $cellY+2
			If $y < 0 Then ContinueLoop
			If $y > $poleSizeY-1 Then ContinueLoop

			If ($aPole[$x][$y] < 10) And ($aPole[$x][$y] >= 1) Then
				$m = 0
				$s = 0
				For $i = -1 To 1
					If $x+$i < 0 Then ContinueLoop
					If $x+$i > $poleSizeX-1 Then ContinueLoop
					For $j = -1 To 1
						If $y+$j < 0 Then ContinueLoop
						If $y+$j > $poleSizeY-1 Then ContinueLoop
						If $aPole[$x+$i][$y+$j] = 11 Then $m += 1
						If $aPole[$x+$i][$y+$j] = 10 Then $s += 1
						If $aPole[$x+$i][$y+$j] < 1 Then $m += $aPole[$x+$i][$y+$j]
					Next
				Next

				If $aPole[$x][$y] = $m  Then
					For $i = -1 To 1
						If $x+$i < 0 Then ContinueLoop
						If $x+$i > $poleSizeX-1 Then ContinueLoop
						For $j = -1 To 1
							If $y+$j < 0 Then ContinueLoop
							If $y+$j > $poleSizeY-1 Then ContinueLoop
							If $aPole[$x+$i][$y+$j] = 10 Then
								If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
									MouseMove(22+16*($x+$i),110+16*($y+$j),0)
									Sleep(100)
									MouseClick("Left", 22+16*($x+$i),110+16*($y+$j))
									ConsoleWrite("вокруг "&$cellX&","&$cellY&" ["&$aPole[$cellX][$cellY]&"] клетка "&$x&","&$y&" ["&$aPole[$x][$y]&"] открыта"&@CR)
									Return True
								EndIf
							EndIf
						Next
					Next
				EndIf

				If $aPole[$x][$y] = ($s+$m)  Then
					For $i = -1 To 1
						If $x+$i < 0 Then ContinueLoop
						If $x+$i > $poleSizeX-1 Then ContinueLoop
						For $j = -1 To 1
							If $y+$j < 0 Then ContinueLoop
							If $y+$j > $poleSizeY-1 Then ContinueLoop
							If $aPole[$x+$i][$y+$j] = 10 Then
								If PixelGetColor(15+16*($x+$i),105+16*($y+$j)) = 0xFFFFFF Then
									MouseMove(22+16*($x+$i),110+16*($y+$j),0)
									Sleep(100)
									MouseClick("Right", 22+16*($x+$i),110+16*($y+$j))
									ConsoleWrite("вокруг "&$cellX&","&$cellY&" ["&$aPole[$cellX][$cellY]&"] клетка "&$x&","&$y&" ["&$aPole[$x][$y]&"] отмечена"&@CR)
									Return True
								EndIf
							EndIf
						Next
					Next
				EndIf

			EndIf
		Next
	Next
	Return False
EndFunc

И да, скрипт работает только для XP.
Размер поля - любой.
:smile:
 

nsgenn

Новичок
Сообщения
52
Репутация
1
C2H5OH

Какое интересное совпадение! , сейчас пишу бота для сапера Win7, боже как же я намучался с определением цифры в клетке, вы не представляете(кто пробовал это сделать, знает почему). Тем не менее подобрал и бот уже делает первый шаг цикла, где выставляет первые флаги. Код правда еще быдловатый, но добившись исполнения алгоритма и оптимизировав его буду исправлять и после выложу пример для W7.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Я пробовал. Но совсем немножко. :smile:
Там *0#@ ! Там цвет клеток меняется слева направо и сверху вниз...

Хотя... Хотя, в моём скрипте все функции, которые идут ниже MinesweeperScan(), никак не зависят от цвета. Все функции связанные с анализом поля можно спокойно переносить в бот для 7-ки.
 

nsgenn

Новичок
Сообщения
52
Репутация
1
C2H5OH
дадада, причем чем дальше к левому нижнему углу, тем цвет приближается к цвету "1" и "4" или к 2ке, если шкурка сапера зеленая.
Делал с проверкой разницы цветов в 0x10-0x20.

Можно на словах как у тебя идет анализ, если не по цвету? Не память ли читаешь?
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
В сапёре для XP цвета у всех клеток одинаковые.
А на 7-ку я забил просто. :smile:
Так что, если ты нашел способ распознавать клетки в сапёре для 7-ки, то весьма любопытно было бы услышать твои идеи.
:idea:
 

nsgenn

Новичок
Сообщения
52
Репутация
1
сейчас правда очень сумбурно и все в куче, но сделал так:

поймал точку на глаз, где 1,2,3,5,6..[+8;+14](для 4 сделал отступ по пикселям -3 по Y) и проверяю эту точку на цвет этой цифры(с диапазоном 0x10 по причине размытой графики цифр). Если нету не одного совпадения, т.е. цикл уже на 9, то сравниваю предыдущую точку с соседней(-3 по оси Х - там уже нету пикселей цифр, но цвет клетки близок), если они равны, то значит эта клетка еще не открыта.
 
Верх