Приложение 3. Примеры обработки событий для таблиц

<< Click to Display Table of Contents >>

Navigation:  Приложения >

Приложение 3. Примеры обработки событий для таблиц

Previous pageReturn to chapter overviewNext page

Пример обработки событий мыши и клавиатуры

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

Интерпретатор языка Lua © ARQA Technologies / http://arqatech.com