热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python数独伪代码回溯法_数独#回溯算法#CTF

1.intro:巅峰极客的一道逆向刷巅峰极客2020里的rev题fu!kpy,复杂得不行但是看到ifd[1][0]!8ord[1][7]!2和ifche

1. intro:巅峰极客的一道逆向

刷巅峰极客2020里的rev题fu!kpy,复杂得不行但是看到if d[1][0] != '8' or d[1][7] != '2'和if check(h1) != 45 or check(h2) != 45 or check(h9) != 45这种内容,结合flag相关的部分可以确认是flag{9*9}的数独。

# uncompyle6 version 2.11.5

# Python bytecode 2.7 (62211)

# Decompiled from: Python 2.7.16 (default, Apr 6 2019, 01:42:57)

# [GCC 8.3.0]

# Embedded file name: test233_ol.py

# Compiled at: 2020-03-20 13:22:50

(lambda __g, __print: [ [ (lambda __after: if __name__ == '__main__':

[ (lambda __after: if len(input) != 87:

(__print('Error len!'), (exit(), __after())[1])[1]__after())(lambda : [ [ [ [ (lambda __after: if fmt1 != 'flag{' or fmt2 != '}':

(__print('Error fmt!'), (exit(0), __after())[1])[1]__after())(lambda : (

d.append(context[0:9]), (d.append(context[9:18]), (d.append(context[18:27]), (d.append(context[27:36]), (d.append(context[36:45]), (d.append(context[45:54]), (d.append(context[54:63]), (d.append(context[63:72]), (d.append(context[72:81]), [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ (lambda __after: if d[0][2] != '5' or d[0][3] != '3':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[1][0] != '8' or d[1][7] != '2':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[2][1] != '7' or d[2][4] != '1' or d[2][6] != '5':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[3][0] != '4' or d[3][5] != '5' or d[3][6] != '3':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[4][1] != '1' or d[4][4] != '7' or d[4][8] != '6':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[5][2] != '3' or d[5][3] != '2' or d[5][7] != '8':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[6][1] != '6' or d[6][3] != '5' or d[6][8] != '9':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[7][2] != '4' or d[7][7] != '3':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if d[8][5] != '9' or d[8][6] != '7':

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check(h1) != 45 or check(h2) != 45 or check(h3) != 45 or check(h4) != 45 or check(h5) != 45 or check(h6) != 45 or check(h7) != 45 or check(h8) != 45 or check(h9) != 45:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check(l1) != 45 or check(l2) != 45 or check(l3) != 45 or check(l4) != 45 or check(l5) != 45 or check(l6) != 45 or check(l7) != 45 or check(l8) != 45 or check(l9) != 45:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check(k1) != 45 or check(k2) != 45 or check(k3) != 45 or check(k4) != 45 or check(k5) != 45 or check(k6) != 45 or check(k7) != 45 or check(k8) != 45 or check(k9) != 45:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check1(h1) != 1 or check1(h2) != 1 or check1(h3) != 1 or check1(h4) != 1 or check1(h5) != 1 or check1(h6) != 1 or check1(h7) != 1 or check1(h8) != 1 or check1(h9) != 1:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check1(l1) != 1 or check1(l2) != 1 or check1(l3) != 1 or check1(l4) != 1 or check1(l5) != 1 or check1(l6) != 1 or check1(l7) != 1 or check1(l8) != 1 or check1(l9) != 1:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (lambda __after: if check1(k1) != 1 or check1(k2) != 1 or check1(k3) != 1 or check1(k4) != 1 or check1(k5) != 1 or check1(k6) != 1 or check1(k7) != 1 or check1(k8) != 1 or check1(k9) != 1:

(__print('Error!'), (exit(), __after())[1])[1]__after())(lambda : (

__print('Yes! You got it!'), __after())[1]))))))))))))))) for __g['k9'] in [context[60] + context[61] + context[62] + context[69] + context[70] + context[71] + context[78] + context[79] + context[80]] ][0] for __g['k8'] in [context[57] + context[58] + context[59] + context[66] + context[67] + context[68] + context[75] + context[76] + context[77]] ][0] for __g['k7'] in [context[54] + context[55] + context[56] + context[63] + context[64] + context[65] + context[72] + context[73] + context[74]] ][0] for __g['k6'] in [context[33] + context[34] + context[35] + context[42] + context[43] + context[44] + context[51] + context[52] + context[53]] ][0] for __g['k5'] in [context[30] + context[31] + context[32] + context[39] + context[40] + context[41] + context[48] + context[49] + context[50]] ][0] for __g['k4'] in [context[27] + context[28] + context[29] + context[36] + context[37] + context[38] + context[45] + context[46] + context[47]] ][0] for __g['k3'] in [context[6] + context[7] + context[8] + context[15] + context[16] + context[17] + context[24] + context[25] + context[26]] ][0] for __g['k2'] in [context[3] + context[4] + context[5] + context[12] + context[13] + context[14] + context[21] + context[22] + context[23]] ][0] for __g['k1'] in [context[0] + context[1] + context[2] + context[9] + context[10] + context[11] + context[18] + context[19] + context[20]] ][0] for __g['l9'] in [context[8] + context[17] + context[26] + context[35] + context[44] + context[53] + context[62] + context[71] + context[80]] ][0] for __g['l8'] in [context[7] + context[16] + context[25] + context[34] + context[43] + context[52] + context[61] + context[70] + context[79]] ][0] for __g['l7'] in [context[6] + context[15] + context[24] + context[33] + context[42] + context[51] + context[60] + context[69] + context[78]] ][0] for __g['l6'] in [context[5] + context[14] + context[23] + context[32] + context[41] + context[50] + context[59] + context[68] + context[77]] ][0] for __g['l5'] in [context[4] + context[13] + context[22] + context[31] + context[40] + context[49] + context[58] + context[67] + context[76]] ][0] for __g['l4'] in [context[3] + context[12] + context[21] + context[30] + context[39] + context[48] + context[57] + context[66] + context[75]] ][0] for __g['l3'] in [context[2] + context[11] + context[20] + context[29] + context[38] + context[47] + context[56] + context[65] + context[74]] ][0] for __g['l2'] in [context[1] + context[10] + context[19] + context[28] + context[37] + context[46] + context[55] + context[64] + context[73]] ][0] for __g['l1'] in [context[0] + context[9] + context[18] + context[27] + context[36] + context[45] + context[54] + context[63] + context[72]] ][0] for __g['h9'] in [context[72:81]] ][0] for __g['h8'] in [context[63:72]] ][0] for __g['h7'] in [context[54:63]] ][0] for __g['h6'] in [context[45:54]] ][0] for __g['h5'] in [context[36:45]] ][0] for __g['h4'] in [context[27:36]] ][0] for __g['h3'] in [context[18:27]] ][0] for __g['h2'] in [context[9:18]] ][0] for __g['h1'] in [context[0:9]] ][0])[1])[1])[1])[1])[1])[1])[1])[1])[1])

for __g['d'] in [[]] ][0]

for __g['context'] in [input[5:-1]] ][0]

for __g['fmt2'] in [input[-1]] ][0]

for __g['fmt1'] in [input[0:5]] ][0])

for __g['input'] in [raw_input('Input your flag:')] ][0]__after())(lambda : None) for __g['check1'], check1.__name__ in [(lambda arg: (lambda __l: [ (lambda __after: if len(list(set(__l['arg']))) != 9:

01)(lambda : None) for __l['arg'] in [arg] ][0])({}), 'check1')] ][0] for __g['check'], check.__name__ in [(lambda arg: (lambda __l: [ sum(map(int, __l['arg'])) for __l['arg'] in [arg] ][0])({}), 'check')] ][0])(globals(), __import__('__builtin__', level=0).__dict__['print'])

熟练的用numpy画出格子,然后发现这道题太难了我不会做。这个时候需要搜一下……

[[0. 0. 5. 3. 0. 0. 0. 0. 0.]

[8. 0. 0. 0. 0. 0. 0. 2. 0.]

[0. 7. 0. 0. 1. 0. 5. 0. 0.]

[4. 0. 0. 0. 0. 5. 3. 0. 0.]

[0. 1. 0. 0. 7. 0. 0. 0. 6.]

[0. 0. 3. 2. 0. 0. 0. 8. 0.]

[0. 6. 0. 5. 0. 0. 0. 0. 9.]

[0. 0. 4. 0. 0. 0. 0. 3. 0.]

[0. 0. 0. 0. 0. 9. 7. 0. 0.]]

2. 知识点引入:backtracking

回溯算法(backtracking)是暴力搜索算法的一种。正是由于回溯算法具有“强大的”暴力搜索的能力,它被应用于一些游戏问题,例如:N 皇后、解数独、祖玛游戏、24 点游戏、走迷宫、生成迷宫。许多复杂的、规模较大的问题都可以使用回溯搜索算法得到所有可行解,进而得到最优解,因此回溯算法有“通用解题方法”的美称,回溯算法也是经典的人工智能的基础算法。

由于回溯算法的时间复杂度很高,因此,在遍历的时候,如果能够提前知道这一条分支不能搜索到满意的结果,这一分支就可以跳过,这一步操作就是在一棵树上剪去一个枝叶,被人们很形象地称之为剪枝。

结论,backtracking可以较好地解数独题。(喂)

2.1. 算法入门-全排列

「力扣」上第 46 号问题:“全排列”。

题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。

在一个树形问题上做一次深度优先遍历。为了理解回溯的过程画个流程图如下。

graph TB;

0--1:depth+=1,state=0b001-->A(1)

A--2:depth+=1,state=0b011-->B("[1,2]")

B--3:depth+=1,state=0b111-->C("[1,2,3]")

C--4:depth-=1,state=0b011-->B

B--5:-depth-=1,state=0b001-->A

A--6:depth+=1,state=0b101-->D("[1,3]")

D--7:depth+=1,state=0b111-->E("[1,3,2]")

E--8:depth-=1,state=0b101-->D

D--9:depth-=1,state=0b001-->A

0(start)

image.png

抄的py3代码如下()。

def permute(nums):

def dfs(nums, size, depth, path, state, res):

# depth满足时递归终止

if depth == size:

res.append(path)

return

for i in range(size):

#print(i,bin(state),path,res)

#state判断第i位的元素是否已经使用过,位运算优化

if ((state >> i) & 1) == 0:

dfs(nums, size, depth &#43; 1, path &#43; [nums[i]], state ^ (1 <

size &#61; len(nums)

if size &#61;&#61; 0:

return []

res &#61; []

dfs(nums, size, 0, [], 0, res)

return res

permute([1,2,3])

2.2. 解数独

乐扣37题&#xff0c;解数独。空白格用 &#39;.&#39; 表示。

数独的规则&#xff1a;

- 数字 1-9 在每一行只能出现一次。

- 数字 1-9 在每一列只能出现一次。

- 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

和原py题一样按照「行优先」的顺序依次枚举每一个空白格中填的数字&#xff0c;通过递归 &#43; 回溯的方法枚举所有可能的填法。

初始化state[row,line,palace]&#xff0c;表明哪些数字已经被使用过了。

尝试去填充数组。如果行、列、 或 3*3 的方格内出现已经被使用过的数字则不填充&#xff0c;否则尝试填充。

填充失败则回溯。

深度满足则递归结束。

为了理解流程&#xff0c;先来个3*3的数独。没有小框框

[[1. 2. 0.]

[2. 0. 1.]

[0. 0. 0.]]

流程图如下。

graph TB;

0--"1:depth&#43;&#61;1,state&#61;[111,011,000,011,010,101]"-->A("[1,2,3],[2,0,1],[0,0,0]")

A--"2:depth&#43;&#61;1,state&#61;[111,111,000,011,110,101]"-->B("[1,2,3],[2,3,1],[0,0,0]")

B--"3:depth&#43;&#61;1,state&#61;[111,111,100,111,110,101]"-->C("[1,2,3],[2,3,1],[3,0,0]")

C--"4:depth&#43;&#61;1,state&#61;[111,111,101,111,111,101]"-->D("[1,2,3],[2,3,1],[3,1,0]")

D--"5:depth&#43;&#61;1,state&#61;[111,111,111,111,111,111]"-->e("[1,2,3],[2,3,1],[3,1,2]")

0("start,depth&#61;4,state&#61;[011,011,000,011,010,001]")

image.png

没时间了抄了份别人的哈希表解法&#xff0c;好清晰啊。以后有空再优化成位运算0.0

def solveSudoku(board):

nums &#61; {"1", "2", "3", "4", "5", "6", "7", "8", "9"}

row &#61; [set() for _ in range(9)]

col &#61; [set() for _ in range(9)]

palace &#61; [[set() for _ in range(3)] for _ in range(3)] # 3*3

blank &#61; [] # 存储待填格的位置

# 初始化&#xff0c;按照行、列、宫 分别存入哈希表

for i in range(9):

for j in range(9):

ch &#61; board[i][j]

if ch &#61;&#61; &#39;0&#39;:

#if ch &#61;&#61; ".":

blank.append((i, j))

else:

row[i].add(ch)

col[j].add(ch)

palace[i // 3][j // 3].add(ch)

def dfs(n):

if n &#61;&#61; len(blank):

return True

i, j &#61; blank[n]

rst &#61; nums - row[i] - col[j] - palace[i // 3][j // 3] # 剩余的数字

if not rst:

return False

for num in rst:

board[i][j] &#61; num

row[i].add(num)

col[j].add(num)

palace[i // 3][j // 3].add(num)

if dfs(n &#43; 1):

return True

row[i].remove(num)

col[j].remove(num)

palace[i // 3][j // 3].remove(num)

dfs(0)

board&#61;[[&#39;0&#39;,&#39;0&#39;,&#39;5&#39;,&#39;3&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;]

,[&#39;8&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;2&#39;,&#39;0&#39;]

,[&#39;0&#39;,&#39;7&#39;,&#39;0&#39;,&#39;0&#39;,&#39;1&#39;,&#39;0&#39;,&#39;5&#39;,&#39;0&#39;,&#39;0&#39;]

,[&#39;4&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;5&#39;,&#39;3&#39;,&#39;0&#39;,&#39;0&#39;]

,[&#39;0&#39;,&#39;1&#39;,&#39;0&#39;,&#39;0&#39;,&#39;7&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;6&#39;]

,[&#39;0&#39;,&#39;0&#39;,&#39;3&#39;,&#39;2&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;8&#39;,&#39;0&#39;]

,[&#39;0&#39;,&#39;6&#39;,&#39;0&#39;,&#39;5&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;9&#39;]

,[&#39;0&#39;,&#39;0&#39;,&#39;4&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;3&#39;,&#39;0&#39;]

,[&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;0&#39;,&#39;9&#39;,&#39;7&#39;,&#39;0&#39;,&#39;0&#39;]]

solveSudoku(board)

from pprint import pprint

pprint(board)

2.3. 来到ctf数独题

其实已经出来了。。只要补一下生成

def solveSudoku(board):

nums &#61; {"1", "2", "3", "4", "5", "6", "7", "8", "9"} #用set保证唯一

row &#61; [set() for _ in range(9)]

col &#61; [set() for _ in range(9)]

palace &#61; [[set() for _ in range(3)] for _ in range(3)] # 3*3

blank &#61; [] # 存储待填格的位置

# 初始化&#xff0c;按照行、列、宫 分别存入哈希表

for i in range(9):

for j in range(9):

ch &#61; board[i][j]

if ch &#61;&#61; &#39;0&#39;:

blank.append((i, j))

else:

row[i].add(ch)

col[j].add(ch)

palace[i // 3][j // 3].add(ch)

def dfs(n):

if n &#61;&#61; len(blank): # 填满

return True

i, j &#61; blank[n]

rst &#61; nums - row[i] - col[j] - palace[i // 3][j // 3] # 剩余的数字

if not rst: # 无解的情况

return False

for num in rst:

board[i][j] &#61; num

row[i].add(num)

col[j].add(num)

palace[i // 3][j // 3].add(num)

if dfs(n &#43; 1):

return True

row[i].remove(num)

col[j].remove(num)

palace[i // 3][j // 3].remove(num)

dfs(0)

import numpy as np

d &#61; np.zeros(81).reshape(9, 9)

d[0][2] &#61; &#39;5&#39;

d[0][3] &#61; &#39;3&#39;

d[1][0] &#61; &#39;8&#39;

d[1][7] &#61; &#39;2&#39;

d[2][1] &#61; &#39;7&#39;

d[2][4] &#61; &#39;1&#39;

d[2][6] &#61; &#39;5&#39;

d[3][0] &#61; &#39;4&#39;

d[3][5] &#61; &#39;5&#39;

d[3][6] &#61; &#39;3&#39;

d[4][1] &#61; &#39;1&#39;

d[4][4] &#61; &#39;7&#39;

d[4][8] &#61; &#39;6&#39;

d[5][2] &#61; &#39;3&#39;

d[5][3] &#61; &#39;2&#39;

d[5][7] &#61; &#39;8&#39;

d[6][1] &#61; &#39;6&#39;

d[6][3] &#61; &#39;5&#39;

d[6][8] &#61; &#39;9&#39;

d[7][2] &#61; &#39;4&#39;

d[7][7] &#61; &#39;3&#39;

d[8][5] &#61; &#39;9&#39;

d[8][6] &#61; &#39;7&#39;

board &#61; d

board&#61; np.asarray(board,dtype&#61;np.int16)

board &#61; np.asarray(board,dtype&#61;np.unicode_)

solveSudoku(board)

for i in board:

print(&#39;&#39;.join(i),end&#61;&#39;&#39;)

flag{145327698839654127672918543496185372218473956753296481367542819984761235521839764}

3. 总结

机器学习赶紧接着学啊&#xff01;

继续学A* 算法解迷宫题啊&#xff01;手动解迷宫你也好意思&#xff1f;()

现在安全竞赛是不是越来越往算法大赛转了。。。落后专业人才转型迫在眉睫。



推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
author-avatar
泉怪的皮毛_884
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有