Пример обработки событий мыши и клавиатуры
Пример реализации игры «Крестики-нолики»
stopped = false
t_id = nil
old_message = message
local fmt = string.format
function message(v, t)
t= t or 1
old_message(tostring(v), t)
end
function OnStop(s)
stopped = true
if t_id~= nil then
DestroyTable(t_id)
end
end
event_table = {
[QTABLE_LBUTTONDOWN] = "Нажали левую кнопку мыши",
[QTABLE_RBUTTONDOWN] = "Нажали правую кнопку мыши",
[QTABLE_LBUTTONDBLCLK] = "Левый даблклик",
[QTABLE_RBUTTONDBLCLK] = "Правый даблклик",
[QTABLE_SELCHANGED] ="Изменилась строка",
[QTABLE_CHAR] = "Символьная клавиша",
[QTABLE_VKEY] = "Еще какая-то клавиша",
[QTABLE_CONTEXTMENU] = "Контекстное меню",
[QTABLE_MBUTTONDOWN] = "Нажали на колесико мыши",
[QTABLE_MBUTTONDBLCLK] = "Даблклик колесом",
[QTABLE_LBUTTONUP] = "Отпустили левую кнопку мыши",
[QTABLE_RBUTTONUP] = "Отпустили правую кнопку мыши",
[QTABLE_CLOSE] = "Закрыли таблицу"
}
function event_callback_str(t_id, msg, par1, par2)
local str = fmt("%s, par1 = %d, par2 = %d", event_table[msg], par1, par2)
SetWindowCaption(t_id, str)
message(str)
end
local p_row = -1
local p_col = -1
function event_callback_color(t_id, msg, par1, par2)
if par1==3 and par2 == 1 then
os.exit()
end
if msg == QTABLE_LBUTTONDOWN then
if p_col ~= -1 and p_col ~= -1 then
SetColor(t_id, p_row, p_col, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR)
end
SetColor(t_id, par1, par2, RGB(240, 128, 128), QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR)
p_row = par1
p_col = par2
end
end
function main()
data = {
{"1", 2, 20130530},
{"4", 5, 20130529},
{"7", 8, 20130528}
}
t_id = AllocTable()
message (t_id)
AddColumn(t_id, 1, "строка", true, QTABLE_CACHED_STRING_TYPE, 10)
AddColumn(t_id, 2, "число", true, QTABLE_INT_TYPE, 10)
AddColumn(t_id, 3, "дата", true, QTABLE_DATE_TYPE, 10)
CreateWindow(t_id)
for _, v in pairs(data) do
row = InsertRow(t_id, -1)
SetCell(t_id, row, 1, v[1])
SetCell(t_id, row, 2, string.format("value = %d",v[2]), v[2])
SetCell(t_id, row, 3, string.format("%04d - %02d - %02d",v[3]/10000, (v[3]%10000)/100, v[3]%100), v[3])
end
SetWindowCaption(t_id, "EXAMPLE")
SetTableNotificationCallback(t_id, event_callback_str)
sleep(5000)
SetTableNotificationCallback(t_id, event_callback_color)
SetCell(t_id, 3, 1, "DO NOT CLICK ME")
SetTableNotificationCallback(t_id, dummy)
while not stopped do
sleep(100)
end
end
--[[ TIC-TAC-TOE
by Evan Hahn (http://evanhahn.com/how-to-code-tic-tac-toe-and-a-lua-implementation/
--]]
----------------------------------------------
-- Configuration (change this if you wish!) --
----------------------------------------------
t_id=nil --grid
-- Are they playable by human or computer-controlled?
PLAYER_1_HUMAN = true
PLAYER_2_HUMAN = false
-- Board size
BOARD_RANK = 3 -- The board will be this in both dimensions.
-- Display stuff
PLAYER_1 = "[x]" -- Player 1 is represented by this. Player 1 goes first.
PLAYER_2 = "[o]" -- Player 2 is represented by this.
EMPTY_SPACE = "[ ]" -- An empty space is displayed like this.
DISPLAY_HORIZONTAL_SEPARATOR = "-" -- Horizontal lines look like this.
DISPLAY_VERTICAL_SEPARATOR = " | " -- Vertical lines look like this
--[[ ###################################################################
#### Don't mess with things below here unless you are brave ####
################################################################### --]]
------------------------
-- More configuration --
------------------------
MAX_BOARD_RANK = 100 -- Won't run above this number. Prevents crashes.
-------------------------------------------------------
-- Don't run if the board is larger than the maximum --
-------------------------------------------------------
if BOARD_RANK > MAX_BOARD_RANK then os.exit(0) end
-----------------------------
-- Create board (2D table) --
-----------------------------
space = {}
for i = 0, (BOARD_RANK - 1) do
space[i] = {}
for j = 0, (BOARD_RANK - 1) do
space[i][j] = nil -- start each space with nil
end
end
---------------------
-- Board functions --
---------------------
-- get the piece at a given spot
function getPiece(x, y)
return space[x][y]
end
-- get the piece at a given spot; if nil, return " "
-- this is useful for output.
function getPieceNoNil(x, y)
if getPiece(x, y) ~= nil then
return getPiece(x, y)
else
return EMPTY_SPACE
end
end
-- is that space empty?
function isEmpty(x, y)
if getPiece(x, y) == nil then
return true
else
return false
end
end
-- place a piece there, but make sure nothing is there already.
-- if you can't play there, return false.
function placePiece(x, y, piece)
if isEmpty(x, y) == true then
space[x][y] = piece
return true
else
return false
end
end
-- is the game over?
function isGameOver()
if checkWin() == false then -- if there is no win...
for i = 0, (BOARD_RANK - 1) do -- is the board empty?
for j = 0, (BOARD_RANK - 1) do
if isEmpty(i, j) == true then return false end
end
end
return true
else -- there is a win; the game is over
return true
end
end
-- create a string made up of a certain number of smaller strings
-- this is useful for the display.
function repeatString(to_repeat, amount)
if amount <= 0 then return "" end
local to_return = ""
for i = 1, amount do
to_return = to_return .. to_repeat
end
return to_return
end
-- display the board.
-- this uses the configuration file pretty much entirely.
function displayBoard()
for i = (BOARD_RANK - 1), 0, -1 do
for j = 0, (BOARD_RANK - 1) do -- generate that row
local piece = getPieceNoNil(j, i)
SetCell(t_id, i+1, j+1, piece)
end
end
end
-------------------------------------------------
-- Create regions (I admit this is a bit ugly) --
-------------------------------------------------
-- declare region and a number to increment
region = {}
region_number = 0
-- vertical
for i = 0, (BOARD_RANK - 1) do
region[region_number] = {}
for j = 0, (BOARD_RANK - 1) do
region[region_number][j] = {}
region[region_number][j]["x"] = i
region[region_number][j]["y"] = j
end
region_number = region_number + 1
end
-- horizontal
for i = 0, (BOARD_RANK - 1) do
region[region_number] = {}
for j = 0, (BOARD_RANK - 1) do
region[region_number][j] = {}
region[region_number][j]["x"] = j
region[region_number][j]["y"] = i
end
region_number = region_number + 1
end
-- diagonal, bottom-left to top-right
region[region_number] = {}
for i = 0, (BOARD_RANK - 1) do
region[region_number][i] = {}
region[region_number][i]["x"] = i
region[region_number][i]["y"] = i
end
region_number = region_number + 1
-- diagonal, top-left to bottom-right
region[region_number] = {}
for i = (BOARD_RANK - 1), 0, -1 do
region[region_number][i] = {}
region[region_number][i]["x"] = BOARD_RANK - i - 1
region[region_number][i]["y"] = i
end
region_number = region_number + 1
----------------------
-- Region functions --
----------------------
-- get a region
function getRegion(number)
return region[number]
end
-- check for a win in a particular region.
-- returns a number representation of the region. occurrences of player 1
-- add 1, occurrences of player 2 subtract 1. so if there are two X pieces,
-- it will return 2. one O will return -1.
function checkWinInRegion(number)
local to_return = 0
for i, v in pairs(getRegion(number)) do
local piece = getPiece(v["x"], v["y"])
if piece == PLAYER_1 then to_return = to_return + 1 end
if piece == PLAYER_2 then to_return = to_return - 1 end
end
return to_return
end
-- check for a win in every region.
-- returns false if no winner.
-- returns the winner if there is one.
function checkWin()
for i in pairs(region) do
local win = checkWinInRegion(i)
if math.abs(win) == BOARD_RANK then
if win == math.abs(win) then
return PLAYER_1
else
return PLAYER_2
end
end
end
return false
end
------------------
-- UI Functions --
------------------
-- human play
function humanPlay(piece)
message("Human turn")
displayBoard()
local placed = false
while placed == false do -- loop until they play correctly
sleep(100)
if g_X ~= -1 and g_Y ~=-1 then
local x = tonumber(g_Y)-1
local y = tonumber(g_X)-1
g_X = -1
g_Y= -1
message("clicked in " .. x .. " and " .. y)
placed = placePiece(x, y, piece)
if placed == false then
message("I'm afraid you can't play there!")
end
end
end
displayBoard()
end
-- AI play
function AIPlay(piece)
-- am I negative or positive?
local me = 0
if piece == PLAYER_1 then me = 1 end
if piece == PLAYER_2 then me = -1 end
-- look for a region in which I can win
for i in pairs(region) do
local win = checkWinInRegion(i)
if win == ((BOARD_RANK - 1) * me) then
for j, v in pairs(getRegion(i)) do
if isEmpty(v["x"], v["y"]) == true then
placePiece(v["x"], v["y"], piece)
return
end
end
end
end
-- look for a region in which I can block
for i in pairs(region) do
local win = checkWinInRegion(i)
if win == ((BOARD_RANK - 1) * (me * -1)) then
for j, v in pairs(getRegion(i)) do
if isEmpty(v["x"], v["y"]) == true then
placePiece(v["x"], v["y"], piece)
return
end
end
end
end
-- play first empty space, if no better option
for i = 0, (BOARD_RANK - 1) do
for j = 0, (BOARD_RANK - 1) do
if placePiece(i, j, piece) ~= false then return end
end
end
end
g_X=-1
g_Y=-1
function event_callback(t_id, msg, par1, par2)
if msg == QTABLE_LBUTTONDOWN then
g_X = par1
g_Y = par2
end
end
old_message = message
local fmt = string.format
function message(v, t)
t= t or 1
old_message(tostring(v), t)
end
function main()
t_id = AllocTable()
AddColumn(t_id, 1, "", true, QTABLE_CACHED_STRING_TYPE, 5)
AddColumn(t_id, 2, "", true, QTABLE_CACHED_STRING_TYPE, 5)
AddColumn(t_id, 3, "", true, QTABLE_CACHED_STRING_TYPE, 5)
CreateWindow(t_id)
for i=1, 3 do
row = InsertRow(t_id, -1)
SetCell(t_id, row, 1, "[ ]")
SetCell(t_id, row, 2, "[ ]")
SetCell(t_id, row, 3, "[ ]")
end
SetTableNotificationCallback(t_id, event_callback)
message("Welcome to Tic-Tac-Toe!")
-- play the game until someone wins
while true do
sleep(100)
-- break if the game is won
if isGameOver() == true then
break
end
-- player 1
if PLAYER_1_HUMAN == true then
humanPlay(PLAYER_1)
else
AIPlay(PLAYER_1)
end
if isGameOver() == true then
break
end
if PLAYER_2_HUMAN == true then
humanPlay(PLAYER_2)
else
AIPlay(PLAYER_2)
end
end
-- show the final board
displayBoard()
-- write who won, or if there is a tie
win = checkWin()
if win == false then
message("Tie game!\n")
else
message(win)
message(" wins!\n")
end
end