refactoring: using UI components
This commit is contained in:
		
							parent
							
								
									2cc3e856c5
								
							
						
					
					
						commit
						2ab5e1a811
					
				
							
								
								
									
										30
									
								
								config.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								config.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| return { | ||||
|     board = "/home/reza/p/lua/22.sudoku/boards/veryhard/27.txt", | ||||
|     window = { | ||||
|         bgColor = "FFFFFF", | ||||
|         width = nil, | ||||
|         height = nil, | ||||
|     }, | ||||
|     TextBox = { | ||||
| 
 | ||||
|     }, | ||||
|     SudokuCanvas = { | ||||
|         colors = { | ||||
|             thickLines = "000000", | ||||
|             thinLines = "808080", | ||||
|             smallNumbersDisabled = "EEEEEE", | ||||
|             smallNumbersEnabled = "FFA500", | ||||
|             bigNumbersTyped = "000000", | ||||
|             bigNumbersHandWritten = "0000FF", | ||||
|             bigNumbersError = "FF0000", | ||||
|             cursorEditBig = "0000FF", | ||||
|             cursorEditSmall = "00FF00", | ||||
|             cursorNoEdit = "FF0000", | ||||
|         }, | ||||
|         fonts = { | ||||
|             small= "", | ||||
|             typedBig = "",  | ||||
|             handWrittenBig = "ui/fonts/Armadillo.ttf", | ||||
|         } | ||||
|     }, | ||||
| } | ||||
							
								
								
									
										53
									
								
								main.lua
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								main.lua
									
									
									
									
									
								
							| @ -1,12 +1,9 @@ | ||||
| TextBox = require "ui.textbox" | ||||
| require "ui.globals" | ||||
| require "ui.config" | ||||
| require "ui.colors" | ||||
| require "ui.init" | ||||
| require "ui.draw" | ||||
| require "ui.keyboard" | ||||
| require "ui.mouse" | ||||
| require "sudoku.utils" | ||||
| uiUtils = require "ui.utils" | ||||
| config = require "config" | ||||
| SudokuCanvas = require "ui.sudokucanvas" | ||||
| 
 | ||||
| board = {} | ||||
| 
 | ||||
| function love.load() | ||||
|     love.window.setTitle("Sudoku!") | ||||
| @ -14,32 +11,26 @@ function love.load() | ||||
|     love.mouse.setGrabbed(false) | ||||
|     love.keyboard.setKeyRepeat(true) | ||||
|     math.randomseed(os.time()) | ||||
|     messages[1] = "Game Info" | ||||
|     board[1] = loadBoard(board.fn) | ||||
|     board[2] = cloneBoard(board[1]) | ||||
|     uiBoard[1] = cloneBoard(board[1]) | ||||
|     uiBoard[2] = cloneBoard(board[1]) | ||||
|     uiBoard[3] = cloneBoard(board[1]) | ||||
|     inputBox = TextBox(50, 50, 500, 45) | ||||
|     inputBox.focused = false | ||||
|     inputBox.enabled = false | ||||
|     initUI() | ||||
| end | ||||
| 
 | ||||
| function love.update(dt) | ||||
|     inputBox:blink(dt) | ||||
|     local board = loadBoard("/home/reza/p/lua/22.sudoku/boards/veryhard/27.txt") | ||||
|     local width, height = love.graphics.getDimensions() | ||||
|     sudokuCanvas = SudokuCanvas:new(200, 100, height/1.5, config.SudokuCanvas) | ||||
|     sudokuCanvas:setBoard(board) | ||||
|     myFont = love.graphics.newFont(24) | ||||
| end | ||||
| 
 | ||||
| function love.draw() | ||||
|     setBackgroundColor(colors.backGround) | ||||
|     drawGrid() | ||||
|     drawSmallNumbers() | ||||
|     drawBigNumbers() | ||||
|     drawCursor() | ||||
|     drawMessages() | ||||
|     inputBox:draw() | ||||
|     uiUtils.setBackgroundColor(config.window.bgColor) | ||||
|     sudokuCanvas:draw() | ||||
| end | ||||
| 
 | ||||
| function love.textinput(t) | ||||
|     inputBox:append(t) | ||||
| function love.keypressed(key) | ||||
|     sudokuCanvas:keypressed(key) | ||||
|     local shift = love.keyboard.isDown('rshift') or love.keyboard.isDown('lshift') | ||||
|     if key == "escape" or key == "q" then | ||||
|         love.event.quit() | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function love.mousepressed(x, y, button, istouch) | ||||
|     sudokuCanvas:mousepressed(x, y, button) | ||||
| end | ||||
|  | ||||
| @ -1,19 +0,0 @@ | ||||
| require "ui.globals" | ||||
| 
 | ||||
| local cached_colors = {} | ||||
| function cHex(rgb) | ||||
|     if cached_colors[rgb] then return unpack(cached_colors[rgb]) end | ||||
|     r = tonumber(string.sub(rgb, 1, 2), 16) / 255 | ||||
|     g = tonumber(string.sub(rgb, 3, 4), 16) / 255 | ||||
|     b = tonumber(string.sub(rgb, 5, 6), 16) / 255 | ||||
|     cached_colors[rgb] = {r, g, b} | ||||
|     return r, g, b | ||||
| end | ||||
| 
 | ||||
| function setBackgroundColor(c) | ||||
|     love.graphics.setBackgroundColor(cHex(c)) | ||||
| end | ||||
| 
 | ||||
| function setColor(c) | ||||
|     love.graphics.setColor(cHex(c)) | ||||
| end | ||||
| @ -1,32 +0,0 @@ | ||||
| require "ui.globals" | ||||
| 
 | ||||
| grid.x1 = 300 | ||||
| grid.y1 = 150 | ||||
| 
 | ||||
| cell.width = 90 | ||||
| cell.height = 90 | ||||
| cell.mx = 10             -- margin x | ||||
| cell.my = 5              -- margin y | ||||
| 
 | ||||
| -- fonts.bigNumbersOriginal = love.graphics.newFont("ui/fonts/Helvetica.ttf", 64) | ||||
| fonts.bigNumbersOriginal = love.graphics.newFont(64) | ||||
| fonts.bigNumbersPlayer = love.graphics.newFont("ui/fonts/Armadillo.ttf", 64) | ||||
| fonts.smallNum = love.graphics.newFont(24) | ||||
| fonts.info = love.graphics.newFont(24) | ||||
| 
 | ||||
| colors.smallNumbersDisabled = "EEEEEE" | ||||
| colors.smallNumbersEnabled = "FFA500" | ||||
| colors.bigNumbersOriginal = "000000" | ||||
| colors.bigNumbersPlayer = "0000FF" | ||||
| colors.cursorActiveSmall = "00FF00" | ||||
| colors.cursorActiveBig = "0000FF" | ||||
| colors.cursorDisabled = "FF0000" | ||||
| colors.backGround = "FFFFFF" | ||||
| colors.messagesText = "000000" | ||||
| colors.boardThinLines = "808080" | ||||
| colors.boardThikLines = "000000" | ||||
| 
 | ||||
| board.fn = "boards/veryhard/01.txt" | ||||
| board.fn = "boards/easy/03.txt" | ||||
| board.fn = "boards/hard/04.txt" | ||||
| board.fn = "boards/veryhard/27.txt" | ||||
							
								
								
									
										81
									
								
								ui/draw.lua
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								ui/draw.lua
									
									
									
									
									
								
							| @ -1,81 +0,0 @@ | ||||
| require "ui.globals" | ||||
| require "ui.colors" | ||||
| 
 | ||||
| function drawGrid() | ||||
|     love.graphics.setLineWidth(1) | ||||
|     setColor(colors.boardThinLines) | ||||
|     for i = 1, 6 do | ||||
|         love.graphics.line(grid.vline[i].x1, grid.vline[i].y1, grid.vline[i].x2, grid.vline[i].y2) | ||||
|         love.graphics.line(grid.hline[i].x1, grid.hline[i].y1, grid.hline[i].x2, grid.hline[i].y2) | ||||
|     end | ||||
|     love.graphics.setLineWidth(2) | ||||
|     setColor(colors.boardThikLines) | ||||
|     for i = 1, 4 do | ||||
|         love.graphics.line(grid.vbline[i].x1, grid.vbline[i].y1, grid.vbline[i].x2, grid.vbline[i].y2) | ||||
|         love.graphics.line(grid.hbline[i].x1, grid.hbline[i].y1, grid.hbline[i].x2, grid.hbline[i].y2) | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function drawSmallNumbers() | ||||
|     love.graphics.setFont(fonts.smallNum) | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             for i = 1, 9 do | ||||
|                 if uiBoard[2][y][x] == 0 then | ||||
|                     local x1 = smallNumbers[x][y][i].x | ||||
|                     local y1 = smallNumbers[x][y][i].y | ||||
|                     if smallNumbersVal[x][y][i] then | ||||
|                         setColor(colors.smallNumbersEnabled) | ||||
|                     else | ||||
|                         setColor(colors.smallNumbersDisabled) | ||||
|                     end | ||||
|                     love.graphics.print(tostring(i), x1, y1) | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function drawBigNumbers() | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             if uiBoard[1][x][y] ~= 0 then | ||||
|                 local c = tostring(uiBoard[1][x][y]) | ||||
|                 love.graphics.setFont(fonts.bigNumbersOriginal) | ||||
|                 setColor(colors.bigNumbersOriginal) | ||||
|                 love.graphics.print(c, grid[y][x].x1+25, grid[y][x].y1+10) | ||||
|             elseif uiBoard[2][x][y] ~= 0 then | ||||
|                 local c = tostring(uiBoard[2][x][y]) | ||||
|                 love.graphics.setFont(fonts.bigNumbersPlayer) | ||||
|                 setColor(colors.bigNumbersPlayer) | ||||
|                 love.graphics.print(c, grid[y][x].x1+33, grid[y][x].y1+15) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function drawCursor() | ||||
|     local x = grid[cursor.x][cursor.y].x1 | ||||
|     local y = grid[cursor.x][cursor.y].y1 | ||||
|     if uiBoard[1][cursor.y][cursor.x] == 0 then | ||||
|         if cursor.editMode then | ||||
|             setColor(colors.cursorActiveSmall) | ||||
|         else | ||||
|             setColor(colors.cursorActiveBig) | ||||
|         end | ||||
|     else | ||||
|         setColor(colors.cursorDisabled) | ||||
|     end | ||||
|     love.graphics.setLineWidth(3) | ||||
|     love.graphics.rectangle("line", x+3, y+3, cell.width-6, cell.height-6, 10, 10) | ||||
| end | ||||
| 
 | ||||
| function drawMessages() | ||||
|     setColor(colors.backGround) | ||||
|     love.graphics.rectangle("fill", 25, 150, grid.x1- 25 - 2, grid.y2 - grid.y1) | ||||
|     setColor(colors.messagesText) | ||||
|     love.graphics.setFont(fonts.info) | ||||
|     for i, msg in ipairs(messages) do | ||||
|         love.graphics.print(msg, 25, 150 + 24 * (i-1)) | ||||
|     end | ||||
| end | ||||
| @ -1,12 +0,0 @@ | ||||
| grid = {} | ||||
| cell = {} | ||||
| fonts = {} | ||||
| colors = {} | ||||
| messages = {} | ||||
| cursor = {} | ||||
| 
 | ||||
| smallNumbers = {} | ||||
| smallNumbersVal = {} | ||||
| 
 | ||||
| board = {} | ||||
| uiBoard = {} | ||||
							
								
								
									
										86
									
								
								ui/init.lua
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								ui/init.lua
									
									
									
									
									
								
							| @ -1,86 +0,0 @@ | ||||
| function initSmallNumbers() | ||||
|     local dx = math.floor((cell.width - 2 * cell.mx) / 3) + 2 | ||||
|     local dy = math.floor((cell.width - 2 * cell.my) / 3) | ||||
|     for x = 1, 9 do | ||||
|         smallNumbers[x] = {} | ||||
|         smallNumbersVal[x] = {} | ||||
|         for y = 1, 9 do | ||||
|             smallNumbers[x][y] = {} | ||||
|             smallNumbersVal[x][y] = {} | ||||
|             local x1 = grid.x1 + (x - 1) * cell.width | ||||
|             local y1 = grid.y1 + (y - 1) * cell.height | ||||
|             local n = 1 | ||||
|             for j = 1, 3 do | ||||
|                 for i = 1, 3 do | ||||
|                     local x2 = x1 + cell.mx + (i-1) * dx | ||||
|                     local y2 = y1 + cell.my + (j-1) * dy | ||||
|                     smallNumbers[x][y][n] = {x=x2, y=y2} | ||||
|                     smallNumbersVal[x][y][n] = false | ||||
|                     n = n + 1 | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function initGrid() | ||||
|     grid.x2 = grid.x1 + 9 * cell.width | ||||
|     grid.y2 = grid.y1 + 9 * cell.height | ||||
|     for i = 1, 9 do | ||||
|         grid[i] = {} | ||||
|         for j = 1, 9 do | ||||
|             local x = grid.x1 + (i - 1) * cell.width | ||||
|             local y = grid.y1 + (j - 1) * cell.height | ||||
|             grid[i][j] = {x1=x, y1=y, x2=x+cell.width, y2=y+cell.height} | ||||
|         end | ||||
|     end | ||||
|     local n = 0 | ||||
|     local m = 0 | ||||
|     grid.vline = {} | ||||
|     for x = grid.x1, grid.x1 + 9 * cell.width, cell.width do | ||||
|         n = n + 1 | ||||
|         if n % 3 ~= 1 then | ||||
|             m = m + 1 | ||||
|             grid.vline[m] = {x1=x, y1=grid.y1, x2=x, y2=grid.y1+9*cell.height} | ||||
|         end | ||||
|     end | ||||
|     n = 0 | ||||
|     m = 0 | ||||
|     grid.hline = {} | ||||
|     for y = grid.y1, grid.y1 + 9 * cell.height, cell.height do | ||||
|         n = n + 1 | ||||
|         if n % 3 ~= 1 then | ||||
|             m = m + 1 | ||||
|             grid.hline[m] = {x1=grid.x1, y1=y, x2=grid.x1+9*cell.width, y2=y} | ||||
|         end | ||||
|     end | ||||
|     n = 0 | ||||
|     grid.vbline = {} | ||||
|     for x = grid.x1, grid.x1+9 * cell.width, cell.width * 3 do | ||||
|         n = n + 1 | ||||
|         grid.vbline[n] = {x1=x, y1=grid.y1, x2=x, y2=grid.y1+9*cell.height} | ||||
|     end | ||||
|     n = 0 | ||||
|     grid.hbline = {} | ||||
|     for y = grid.y1, grid.y1+9*cell.height, cell.height * 3 do | ||||
|         n = n + 1 | ||||
|         grid.hbline[n] = {x1=grid.x1, y1=y, x2=grid.x1+9*cell.width, y2=y} | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function findFirstEmptyCell() | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             if uiBoard[1][y][x] == 0 then return y, x end | ||||
|         end | ||||
|     end | ||||
|     return -1, -1 | ||||
| end | ||||
| 
 | ||||
| function initUI() | ||||
|     initSmallNumbers() | ||||
|     initGrid() | ||||
|     cursor.x, cursor.y = findFirstEmptyCell() | ||||
|     cursor.editMode = false | ||||
|     cursor.lastEditMode = false | ||||
| end | ||||
							
								
								
									
										138
									
								
								ui/keyboard.lua
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								ui/keyboard.lua
									
									
									
									
									
								
							| @ -1,138 +0,0 @@ | ||||
| require "sudoku.sudoku" | ||||
| require "ui.logic" | ||||
| 
 | ||||
| local function iterBoardLine(start, step) | ||||
|     local step = step or 1 | ||||
|     local i = start | ||||
|     local n = 0 | ||||
|     return function() | ||||
|         i = i + step | ||||
|         n = n + 1 | ||||
|         if n > 9 then return end | ||||
|         if i > 9 then i = 1 end | ||||
|         if i < 1 then i = 9 end | ||||
|         return i | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function handleRight(shift) | ||||
|     if shift then | ||||
|         for x in iterBoardLine(cursor.x) do | ||||
|             if uiBoard[1][cursor.y][x] == 0 then | ||||
|                 cursor.x = x | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         cursor.x = cursor.x + 1 | ||||
|         if cursor.x > 9 then cursor.x = 1 end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function handleLeft(shift) | ||||
|     if shift then | ||||
|         for x in iterBoardLine(cursor.x, -1) do | ||||
|             if uiBoard[1][cursor.y][x] == 0 then | ||||
|                 cursor.x = x | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         cursor.x = cursor.x - 1 | ||||
|         if cursor.x < 1 then cursor.x = 9 end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function handleDown(shift) | ||||
|     if shift then | ||||
|         for y in iterBoardLine(cursor.y) do | ||||
|             if uiBoard[1][y][cursor.x] == 0 then | ||||
|                 cursor.y = y | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         cursor.y = cursor.y + 1 | ||||
|         if cursor.y > 9 then cursor.y = 1 end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function handleUp(shift) | ||||
|     if shift then | ||||
|         for y in iterBoardLine(cursor.y, -1) do | ||||
|             if uiBoard[1][y][cursor.x] == 0 then | ||||
|                 cursor.y = y | ||||
|                 break | ||||
|             end | ||||
|         end | ||||
|     else | ||||
|         cursor.y = cursor.y - 1 | ||||
|         if cursor.y < 1 then cursor.y = 9 end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| function love.keypressed(key, scancode) | ||||
|     if inputBox.focused then | ||||
|         if key == "backspace" then | ||||
|             inputBox:delete() | ||||
|         end | ||||
|         return  | ||||
|     end | ||||
|     local shift = love.keyboard.isDown('rshift') or love.keyboard.isDown('lshift') | ||||
|     if key == "escape" or key == "q" then | ||||
|         love.event.quit() | ||||
|     elseif key == "right" or key == "l" then | ||||
|         handleRight(shift) | ||||
|     elseif key == "left" or key == "h" then | ||||
|         handleLeft(shift) | ||||
|     elseif key == "down" or key == "j" then | ||||
|         handleDown(shift) | ||||
|     elseif key == "up" or key == "k" then | ||||
|         handleUp(shift) | ||||
|     elseif key == "s" then | ||||
|         displaySearchSpace() | ||||
|     elseif key == "c" then | ||||
|         checkBoard() | ||||
|     elseif key == "f2" then | ||||
|         saveCurrentBoard() | ||||
|     elseif key == "f3" then | ||||
|         loadLastBoard() | ||||
|     elseif uiBoard[1][cursor.y][cursor.x] == 0 then | ||||
|         local n = tonumber(key) or -1 | ||||
|         if n > 0 and n < 10 then | ||||
|             if shift or cursor.editMode then | ||||
|                 uiBoard[2][cursor.y][cursor.x] = 0 | ||||
|                 cursor.editMode = true | ||||
|                 smallNumbersVal[cursor.x][cursor.y][n] = not smallNumbersVal[cursor.x][cursor.y][n] | ||||
|             else | ||||
|                 -- for i = 1, 9 do | ||||
|                 --     smallNumbersVal[cursor.x][cursor.y][i] = false | ||||
|                 -- end | ||||
|                 uiBoard[2][cursor.y][cursor.x] = n | ||||
|                 uiBoard[3][cursor.y][cursor.x] = n | ||||
|             end | ||||
|         elseif key == "delete" or key == "0" then | ||||
|             if uiBoard[2][cursor.y][cursor.x] ~= 0 then | ||||
|                 uiBoard[2][cursor.y][cursor.x] = 0 | ||||
|             else | ||||
|                 if uiBoard[1][cursor.y][cursor.x] == 0 then | ||||
|                     for i = 1, 9 do | ||||
|                         smallNumbersVal[cursor.x][cursor.y][i] = false | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|         elseif key == "tab" then | ||||
|             if cursor.editMode == false then | ||||
|                 uiBoard[3][cursor.y][cursor.x] = uiBoard[2][cursor.y][cursor.x] | ||||
|                 uiBoard[2][cursor.y][cursor.x] = 0 | ||||
|                 cursor.editMode = true | ||||
|             else | ||||
|                 uiBoard[2][cursor.y][cursor.x] = uiBoard[3][cursor.y][cursor.x] | ||||
|                 cursor.editMode = false | ||||
|             end | ||||
|         elseif key == "e" then | ||||
|             inputBox.enabled = true | ||||
|             inputBox.focused = true | ||||
|         end | ||||
|     end | ||||
| end | ||||
							
								
								
									
										42
									
								
								ui/logic.lua
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								ui/logic.lua
									
									
									
									
									
								
							| @ -1,42 +0,0 @@ | ||||
| function displaySearchSpace() | ||||
|     local s = buildSearchSpace(uiBoard[2]) | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             for z = 1, 9 do | ||||
|                 smallNumbersVal[x][y][z] = false | ||||
|             end | ||||
|             for _, v in ipairs(s[y][x]) do | ||||
|                 smallNumbersVal[x][y][v] = true | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     messages = scheck(uiBoard[2]) | ||||
| end | ||||
| 
 | ||||
| function checkBoard() | ||||
|     messages = scheck(uiBoard[2]) | ||||
| end | ||||
| 
 | ||||
| function loadLastBoard() | ||||
|     board = {} | ||||
|     board[1], board[2] = loadBoard("lastBoard.txt") | ||||
|     uiBoard[1] = cloneBoard(board[1]) | ||||
|     uiBoard[2] = cloneBoard(board[2]) | ||||
|     uiBoard[3] = cloneBoard(board[2]) | ||||
|     messages[1] = 'loaded: "lastBoard.txt"' | ||||
| end | ||||
| 
 | ||||
| function saveCurrentBoard() | ||||
|     local f = io.open("lastBoard.txt", "w") | ||||
|     for row = 1, 9 do | ||||
|         f:write(table.concat(uiBoard[1][row], " ")) | ||||
|         f:write("\n") | ||||
|     end | ||||
|     f:write("\n") | ||||
|     for row = 1, 9 do | ||||
|         f:write(table.concat(uiBoard[2][row], " ")) | ||||
|         f:write("\n") | ||||
|     end | ||||
|     f:close() | ||||
|     messages[1] = 'saved: "lastBoard.txt"' | ||||
| end | ||||
							
								
								
									
										37
									
								
								ui/mouse.lua
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								ui/mouse.lua
									
									
									
									
									
								
							| @ -1,37 +0,0 @@ | ||||
| function love.mousepressed(x, y, button, istouch) | ||||
|     local inBoard = false | ||||
|     local canChange = false | ||||
|     local dx = math.floor(cell.width / 3) | ||||
|     local dy = math.floor(cell.height / 3) | ||||
|     local cx = 0 | ||||
|     local cy = 0 | ||||
|     local mx = 0 | ||||
|     local my = 0 | ||||
|     local n = 0 | ||||
|     if x > grid.x1 and x < grid.x2 and y > grid.y1 and y < grid.y2 then | ||||
|         inBoard = true | ||||
|         cx = math.floor((x - grid.x1) / cell.width) + 1 | ||||
|         cy = math.floor((y - grid.y1) / cell.height) + 1 | ||||
|         mx = math.floor((x - grid[cx][cy].x1) / dx) + 1 | ||||
|         my = math.floor((y - grid[cx][cy].y1) / dy) + 1 | ||||
|         n = mx + 3 * (my - 1) | ||||
|         if uiBoard[1][cy][cx] == 0 then canChange = true end | ||||
|     end | ||||
|     if canChange then | ||||
|         if button == 1 then | ||||
|             cursor.editMode = false | ||||
|             uiBoard[2][cy][cx] = uiBoard[3][cy][cx] | ||||
|             cursor.lastEditMode = false | ||||
|         elseif button == 2 then | ||||
|             cursor.editMode = true | ||||
|             uiBoard[3][cy][cx] = uiBoard[2][cy][cx] | ||||
|             uiBoard[2][cy][cx] = 0 | ||||
|             -- if cursor.x == cx and cursor.y == cy and cursor.lastEditMode then | ||||
|             --     smallNumbersVal[cx][cy][n] = not smallNumbersVal[cx][cy][n] | ||||
|             -- end | ||||
|             cursor.lastEditMode = true | ||||
|         end | ||||
|         cursor.x = cx | ||||
|         cursor.y = cy | ||||
|     end | ||||
| end | ||||
							
								
								
									
										407
									
								
								ui/sudokucanvas.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								ui/sudokucanvas.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,407 @@ | ||||
| function table2string(t) | ||||
|     local myself = table2string | ||||
|     local l = {} | ||||
|     local n = 0 | ||||
|     for k, v in pairs(t) do | ||||
|         n = n + 1 | ||||
|         if type(v) == "table" then | ||||
|             l[n] = k .. ': ' .. myself(v) | ||||
|         elseif type(v) == "string" then | ||||
|             l[n] = k .. ': ' .. '"' .. v .. '"' | ||||
|         else | ||||
|             l[n] = k .. ': ' .. v | ||||
|         end | ||||
|     end | ||||
|     return "{" .. table.concat(l, ", ") .. "}" | ||||
| end | ||||
| 
 | ||||
| SudokuCanvas = {} | ||||
| SudokuCanvas.__index = SudokuCanvas | ||||
| 
 | ||||
| local function selectSmallNumbersFont(cellSize) | ||||
|     local fntSize = 65 | ||||
|     local margin = 0 | ||||
|     while fntSize >= 5 do | ||||
|         fntSize = fntSize - 1 | ||||
|         local fnt = love.graphics.newFont(fntSize) | ||||
|         -- margin = math.floor((cellSize - math.floor(fnt:getWidth("123") / 3) * 5) / 2) | ||||
|         margin = math.floor((cellSize - (fnt:getHeight() * 3 + 6)) / 2) | ||||
|         if margin >= 5 then return fnt, margin end | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| local function createSNumTable() | ||||
|     local smallNumbers = {} | ||||
|     for x = 1, 9 do | ||||
|         smallNumbers[x] = {} | ||||
|         for y = 1, 9 do | ||||
|             smallNumbers[x][y] = {} | ||||
|             for num = 1, 9 do | ||||
|                 smallNumbers[x][y][num] = {x=0, y=0, enabled=false} | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     return smallNumbers | ||||
| end | ||||
| 
 | ||||
| local function calSmallNumbersCoordinates(grid, smallNumbers) | ||||
|     local smallNumbers = smallNumbers or createSNumTable() | ||||
|     local cellSize = grid[1][1].x2 - grid[1][1].x1 | ||||
|     local font, my = selectSmallNumbersFont(cellSize) | ||||
|     local mx = math.floor((cellSize - math.floor(font:getWidth("123") / 3) * 5) / 2) | ||||
|     -- local my = math.floor(mx / 2) | ||||
|     local dx = math.floor((cellSize - 2 * mx) / 3) + 2 | ||||
|     local dy = math.floor((cellSize - 2 * my) / 3) + 2 | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             local x1 = grid.x1 + (x - 1) * cellSize | ||||
|             local y1 = grid.y1 + (y - 1) * cellSize | ||||
|             local n = 1 | ||||
|             for j = 1, 3 do | ||||
|                 for i = 1, 3 do | ||||
|                     local x2 = x1 + mx + (i-1) * dx | ||||
|                     local y2 = y1 + my + (j-1) * dy | ||||
|                     smallNumbers[x][y][n].x = x2 | ||||
|                     smallNumbers[x][y][n].y = y2 | ||||
|                     n = n + 1 | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
|     smallNumbers.font = font | ||||
|     return smallNumbers | ||||
| end | ||||
| 
 | ||||
| local function buildBigNumbers(grid, fonts) | ||||
|     local cellSize = grid[1][1].x2 - grid[1][1].x1 | ||||
|     local fntSize = math.floor(cellSize * 0.9) | ||||
|     local bigNumbers = {} | ||||
| 
 | ||||
|     if fonts.typedBig and fonts.typedBig ~= "" then | ||||
|         bigNumbers.typedFont = love.graphics.newFont(fonts.typedBig, fntSize) | ||||
|     else | ||||
|         bigNumbers.typedFont = love.graphics.newFont(fntSize) | ||||
|     end | ||||
|     if fonts.handWrittenBig and fonts.handWrittenBig ~= "" then | ||||
|         bigNumbers.handWrittenFont = love.graphics.newFont(fonts.handWrittenBig, fntSize) | ||||
|     else | ||||
|         bigNumbers.handWrittenFont = love.graphics.newFont(fntSize) | ||||
|     end | ||||
| 
 | ||||
|     local typedHeight = bigNumbers.typedFont:getHeight() | ||||
|     local handWrittenHeight = bigNumbers.handWrittenFont:getHeight() | ||||
|     local typedWidth = {} | ||||
|     local handWrittenWidth = {} | ||||
|     for i = 1, 9 do | ||||
|         local c = tostring(i) | ||||
|         typedWidth[i] = bigNumbers.typedFont:getWidth(c) | ||||
|         handWrittenWidth[i] = bigNumbers.handWrittenFont:getWidth(c) | ||||
|     end | ||||
| 
 | ||||
|     for x = 1, 9 do | ||||
|         bigNumbers[x] = {} | ||||
|         for y = 1, 9 do | ||||
|             bigNumbers[x][y] = {} | ||||
|             local half = math.floor(cellSize / 2) | ||||
|             for num = 1, 9 do | ||||
|                 bigNumbers[x][y][num] = { | ||||
|                     typed = { | ||||
|                         x = grid[x][y].x1 + half - math.floor(typedWidth[num] / 2), | ||||
|                         y = grid[x][y].y1 + half - math.floor(typedHeight / 2), | ||||
|                     }, | ||||
|                     handWritten = { | ||||
|                         x = grid[x][y].x1 + half - math.floor(handWrittenWidth[num] / 2), | ||||
|                         y = grid[x][y].y1 + half - math.floor(handWrittenHeight / 2), | ||||
|                     }, | ||||
|                 } | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
|     return bigNumbers | ||||
| end | ||||
| 
 | ||||
| local function buildGrid(x, y, cellSize) | ||||
|     local grid = {} | ||||
|     grid.x1 = x | ||||
|     grid.y1 = y | ||||
|     grid.x2 = x + 9 * cellSize | ||||
|     grid.y2 = y + 9 * cellSize | ||||
|     for i = 1, 9 do | ||||
|         grid[i] = {} | ||||
|         for j = 1, 9 do | ||||
|             local x = grid.x1 + (i - 1) * cellSize | ||||
|             local y = grid.y1 + (j - 1) * cellSize | ||||
|             grid[i][j] = {x1=x, y1=y, x2=x+cellSize, y2=y+cellSize} | ||||
|         end | ||||
|     end | ||||
|     local n = 0 | ||||
|     local m = 0 | ||||
|     grid.vline = {} | ||||
|     for x = grid.x1, grid.x2, cellSize do | ||||
|         n = n + 1 | ||||
|         if n % 3 ~= 1 then | ||||
|             m = m + 1 | ||||
|             grid.vline[m] = {x1=x, y1=grid.y1, x2=x, y2=grid.y1+9*cellSize} | ||||
|         end | ||||
|     end | ||||
|     n = 0 | ||||
|     m = 0 | ||||
|     grid.hline = {} | ||||
|     for y = grid.y1, grid.y2, cellSize do | ||||
|         n = n + 1 | ||||
|         if n % 3 ~= 1 then | ||||
|             m = m + 1 | ||||
|             grid.hline[m] = {x1=grid.x1, y1=y, x2=grid.x1+9*cellSize, y2=y} | ||||
|         end | ||||
|     end | ||||
|     n = 0 | ||||
|     grid.vbline = {} | ||||
|     for x = grid.x1, grid.x2, cellSize * 3 do | ||||
|         n = n + 1 | ||||
|         grid.vbline[n] = {x1=x, y1=grid.y1, x2=x, y2=grid.y1+9*cellSize} | ||||
|     end | ||||
|     n = 0 | ||||
|     grid.hbline = {} | ||||
|     for y = grid.y1, grid.y2, cellSize * 3 do | ||||
|         n = n + 1 | ||||
|         grid.hbline[n] = {x1=grid.x1, y1=y, x2=grid.x1+9*cellSize, y2=y} | ||||
|     end | ||||
|     return grid | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:resize(size, x, y) | ||||
|     x = x or self.x1 | ||||
|     y = y or self.y1 | ||||
|     self.cellSize = math.floor(size / 9) | ||||
|     self.size = self.cellSize * 9 | ||||
|     self.x1 = x | ||||
|     self.y1 = y | ||||
|     self.x2 = x + size | ||||
|     self.y2 = y + size | ||||
|     self.grid = buildGrid(x, y, self.cellSize) | ||||
|     self.smallNumbers = calSmallNumbersCoordinates(self.grid, self.smallNumbers) | ||||
|     self.bigNumbers = buildBigNumbers(self.grid, self.fonts) | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:setBoard(board, board2) | ||||
|     local board2 = board2 or board | ||||
|     self.board = {} | ||||
|     self.board[1] = cloneBoard(board) | ||||
|     self.board[2] = cloneBoard(board2) | ||||
|     self.board[3] = cloneBoard(board2) | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:new(x, y, size, options) | ||||
|     local options = options or {} | ||||
|     local cellSize = math.floor(size / 9) | ||||
|     local size = cellSize * 9 | ||||
|     local o = { | ||||
|         x1 = x, | ||||
|         y1 = y, | ||||
|         x2 = x + size, | ||||
|         y2 = y + size, | ||||
|         size = size, | ||||
|         cellSize = cellSize, | ||||
|         cursor = {x=1, y=1, mode="big"}, | ||||
|         fonts = options.fonts, | ||||
|         colors = options.colors, | ||||
|         enabled = true, | ||||
|         focused = true, | ||||
|     } | ||||
|     o.grid = buildGrid(x, y, cellSize) | ||||
|     o.smallNumbers = calSmallNumbersCoordinates(o.grid) | ||||
|     o.bigNumbers = buildBigNumbers(o.grid, o.fonts) | ||||
|     if options.enabled == false then o.enabled = false end | ||||
|     if options.focused == false then o.focused = false end | ||||
|     if not o.enabled then o.cursorOn = false; o.focused = false end | ||||
|     setmetatable(o, SudokuCanvas) | ||||
|     return o | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:enable() | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:focus() | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:draw() | ||||
|     local grid = self.grid | ||||
| 
 | ||||
|     -- grid | ||||
|     love.graphics.setLineWidth(1) | ||||
|     uiUtils.setColor(self.colors.thinLines) | ||||
|     for i = 1, 6 do | ||||
|         love.graphics.line(grid.vline[i].x1, grid.vline[i].y1, grid.vline[i].x2, grid.vline[i].y2) | ||||
|         love.graphics.line(grid.hline[i].x1, grid.hline[i].y1, grid.hline[i].x2, grid.hline[i].y2) | ||||
|     end | ||||
|     love.graphics.setLineWidth(2) | ||||
|     uiUtils.setColor(self.colors.thickLines) | ||||
|     for i = 1, 4 do | ||||
|         love.graphics.line(grid.vbline[i].x1, grid.vbline[i].y1, grid.vbline[i].x2, grid.vbline[i].y2) | ||||
|         love.graphics.line(grid.hbline[i].x1, grid.hbline[i].y1, grid.hbline[i].x2, grid.hbline[i].y2) | ||||
|     end | ||||
| 
 | ||||
|     -- smallNumbers | ||||
|     love.graphics.setFont(self.smallNumbers.font) | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             for i = 1, 9 do | ||||
|                 if self.board[2][y][x] == 0 then | ||||
|                     local x1 = self.smallNumbers[x][y][i].x | ||||
|                     local y1 = self.smallNumbers[x][y][i].y | ||||
|                     if self.smallNumbers[x][y][i].enabled then | ||||
|                         uiUtils.setColor(self.colors.smallNumbersEnabled) | ||||
|                     else | ||||
|                         uiUtils.setColor(self.colors.smallNumbersDisabled) | ||||
|                     end | ||||
|                     love.graphics.print(tostring(i), x1, y1) | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
|     -- bigNumbers | ||||
|     for x = 1, 9 do | ||||
|         for y = 1, 9 do | ||||
|             if self.board[1][y][x] ~= 0 then | ||||
|                 -- print(y, x, self.board[1][y][x]) | ||||
|                 local num = self.board[1][y][x] | ||||
|                 local px = self.bigNumbers[x][y][num].typed.x | ||||
|                 local py = self.bigNumbers[x][y][num].typed.y | ||||
|                 love.graphics.setFont(self.bigNumbers.typedFont) | ||||
|                 uiUtils.setColor(self.colors.bigNumbersTyped) | ||||
|                 love.graphics.print(tostring(num), px, py) | ||||
|             elseif self.board[2][y][x] ~= 0 then | ||||
|                 local num = self.board[2][y][x] | ||||
|                 local px = self.bigNumbers[x][y][num].handWritten.x | ||||
|                 local py = self.bigNumbers[x][y][num].handWritten.y | ||||
|                 love.graphics.setFont(self.bigNumbers.handWrittenFont) | ||||
|                 uiUtils.setColor(self.colors.bigNumbersHandWritten) | ||||
|                 love.graphics.print(tostring(num), px, py) | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
|     -- cursor | ||||
|     local x = grid[self.cursor.x][self.cursor.y].x1 | ||||
|     local y = grid[self.cursor.x][self.cursor.y].y1 | ||||
|     if self.board[1][self.cursor.y][self.cursor.x] == 0 then | ||||
|         if self.cursor.mode == "big" then | ||||
|             uiUtils.setColor(self.colors.cursorEditBig) | ||||
|         else | ||||
|             uiUtils.setColor(self.colors.cursorEditSmall) | ||||
|         end | ||||
|     else | ||||
|         uiUtils.setColor(self.colors.cursorNoEdit) | ||||
|     end | ||||
|     love.graphics.setLineWidth(3) | ||||
|     love.graphics.rectangle("line", x+3, y+3, self.cellSize-6, self.cellSize-6, 10, 10) | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:keypressed(key) | ||||
|     local x = self.cursor.x | ||||
|     local y = self.cursor.y | ||||
|     local mode = self.cursor.mode | ||||
|     if key == "-" then | ||||
|         local size = self.size - math.floor(self.size * .05) | ||||
|         if size >= 300 then | ||||
|             self:resize(size) | ||||
|         end | ||||
|     elseif key == "=" then | ||||
|         size = self.size + math.floor(self.size * .05) | ||||
|         self:resize(size) | ||||
|     elseif key:match("[1-9]") then | ||||
|         local num = key:byte() - 48 | ||||
|         if self.board[1][y][x] == 0 then | ||||
|             if mode == "big" then | ||||
|                 self.board[2][y][x] = num | ||||
|                 self.board[3][y][x] = num | ||||
|             else | ||||
|                 self.smallNumbers[x][y][num].enabled = not self.smallNumbers[x][y][num].enabled | ||||
|             end | ||||
|         end | ||||
|     elseif key == "delete" or key == "0" then | ||||
|         if self.board[1][y][x] == 0 then | ||||
|             if mode == "big" then | ||||
|                 self.board[2][y][x] = 0 | ||||
|                 self.board[3][y][x] = 0 | ||||
|             else | ||||
|                 for num = 1, 9 do | ||||
|                     self.smallNumbers[x][y][num].enabled = false | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     elseif key == "right" or key == "l" then | ||||
|         x = x + 1 | ||||
|         if x > 9 then x = 1 end | ||||
|     elseif key == "left" or key == "h" then | ||||
|         x = x - 1 | ||||
|         if x < 1 then x = 9 end | ||||
|     elseif key == "down" or key == "j" then | ||||
|         y = y + 1 | ||||
|         if y > 9 then y = 1 end | ||||
|     elseif key == "up" or key == "k" then | ||||
|         y = y - 1 | ||||
|         if y < 1 then y = 9 end | ||||
|     elseif key == "tab" then | ||||
|         if mode == "big" then | ||||
|             self.board[3][y][x] = self.board[2][y][x] | ||||
|             self.board[2][y][x] = 0 | ||||
|             mode = "small" | ||||
|         else | ||||
|             self.board[2][y][x] = self.board[3][y][x] | ||||
|             mode = "big" | ||||
|         end | ||||
|     end | ||||
|     self.cursor.x = x | ||||
|     self.cursor.y = y | ||||
|     self.cursor.mode = mode | ||||
| end | ||||
| 
 | ||||
| function SudokuCanvas:mousepressed(x, y, button, istouch) | ||||
|     local grid = self.grid | ||||
|     local inBoard = false | ||||
|     local canChange = false | ||||
|     local isSameCell = false | ||||
|     local dx = math.floor(self.cellSize / 3) | ||||
|     local cx = 0 | ||||
|     local cy = 0 | ||||
|     local mode = self.cursor.mode | ||||
|     local mx = 0 | ||||
|     local my = 0 | ||||
| 
 | ||||
|     local n = 0 | ||||
|     if x > grid.x1 and x < grid.x2 and y > grid.y1 and y < grid.y2 then | ||||
|         inBoard = true | ||||
|         cx = math.floor((x - grid.x1) / self.cellSize) + 1 | ||||
|         cy = math.floor((y - grid.y1) / self.cellSize) + 1 | ||||
|         mx = math.floor((x - grid[cx][cy].x1) / dx) + 1 | ||||
|         my = math.floor((y - grid[cx][cy].y1) / dx) + 1 | ||||
|         num = mx + 3 * (my - 1) | ||||
|         if self.board[1][cy][cx] == 0 then canChange = true end | ||||
|         if self.cursor.x == cx and self.cursor.y == cy then isSameCell = true end | ||||
|     end | ||||
|     if canChange then | ||||
|         if button == 1 then | ||||
|             if isSameCell and self.cursor.mode == "small" then | ||||
|                 self.smallNumbers[cx][cy][num].enabled = not self.smallNumbers[cx][cy][num].enabled | ||||
|             end | ||||
|         elseif button == 2 then | ||||
|             if isSameCell then | ||||
|                 if self.cursor.mode == "big" then | ||||
|                     self.board[2][cy][cx] = 0 | ||||
|                     self.cursor.mode = "small" | ||||
|                 else | ||||
|                     self.cursor.mode = "big" | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
| 
 | ||||
|         self.cursor.x = cx | ||||
|         self.cursor.y = cy | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| setmetatable(SudokuCanvas, {__call=SudokuCanvas.new}) | ||||
| return SudokuCanvas | ||||
							
								
								
									
										29
									
								
								ui/utils.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								ui/utils.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| uiUtils = {} | ||||
| 
 | ||||
| local cached_colors = {} | ||||
| function uiUtils.cHex(rgb) | ||||
|     if cached_colors[rgb] then return unpack(cached_colors[rgb]) end | ||||
|     r = tonumber(string.sub(rgb, 1, 2), 16) / 255 | ||||
|     g = tonumber(string.sub(rgb, 3, 4), 16) / 255 | ||||
|     b = tonumber(string.sub(rgb, 5, 6), 16) / 255 | ||||
|     cached_colors[rgb] = {r, g, b} | ||||
|     return r, g, b | ||||
| end | ||||
| 
 | ||||
| function uiUtils.convertColors(ct) | ||||
|     local nct = {} | ||||
|     for k, v in pairs(ct) do | ||||
|         nct[k] = uiUtils.cHex(v) | ||||
|     end | ||||
|     return nct | ||||
| end | ||||
| 
 | ||||
| function uiUtils.setBackgroundColor(c) | ||||
|     love.graphics.setBackgroundColor(uiUtils.cHex(c)) | ||||
| end | ||||
| 
 | ||||
| function uiUtils.setColor(c) | ||||
|     love.graphics.setColor(uiUtils.cHex(c)) | ||||
| end | ||||
| 
 | ||||
| return uiUtils | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user