文章目录

  • 前言
  • 博弈树
  • 博弈算法
    • 打分机制的确定
    • 极大极小算法
    • alpha-beta剪枝
    • 启发式搜索
  • 代码实现

前言

周末在家闲来无事,下起了五子棋。其中人机对战部分引起了我的好奇,机器人如何实现自动下棋的功能的呢?带着如此疑问,我踏上了探寻真相的旅程!

博弈树

众所周知,评判一个人棋力如何就是判断其思考的深度。一个人棋力越厉害,其思考深度越深。对于AI来说也是一样,最常用的对弈数据结构为博弈树,博弈树(game tree)是一种特殊的根树,博弈树可以表示两名游戏参与者之间的一场博弈(游戏),他们交替行棋,试图获胜。我们以最简单的井字棋为例:


对于9宫格我们进行标号,如果我方先走一步5,那么就形成以下博弈树,也就是落子枚举:

然而如果想要确定最优解,就需要引入评分机制,这就引出了极大极小算法。

博弈算法

常用的博弈算法为极大极小算法:
对于博弈树而言,树的叶子节点就是游戏的一个局面。极大极小算法利用的原理就是对手与自己都会选择最有利于自己的局面。这就需要一套打分机制,越有利于对手的局面,所得的分数越少,越有利于自己的局面,所得的分数越高。

打分机制的确定

对于五子棋而言,为了满足越有利于对手的局面,所得的分数越少,越有利于自己的局面,所得的分数越高的设定,如何进行局面分数评估呢?这边确定了如下规则:

  • 如果我方局面中出现活1,+10分
  • 如果我方局面中出现活2,+100分
  • 如果我方局面中出现活3,+1000分
  • 如果我方局面中出现活4,+10000分
  • 如果我方局面中出现五连,+100000分
  • 如果我方局面中出现死2,+10分
  • 如果我方局面中出现死3,+100分
  • 如果我方局面中出现死4,+1000分
  • 如果对方局面中出现活1,-10分
  • 如果对方局面中出现活2,-100分
  • 如果对方局面中出现活3,-1000分
  • 如果对方局面中出现活4,-10000分
  • 如果对方局面中出现五连,-100000分
  • 如果对方局面中出现死2,-10分
  • 如果对方局面中出现死3,-100分
  • 如果对方局面中出现死4,-1000分

对于一个局面,遍历棋盘所有位置,根据以上规则所有分数总和即为当前局面的分数。
go语言实现:

type ScoreMap struct {role  []intscore int
}func InitScoreMapList() []ScoreMap {scoreMapList := []ScoreMap{}//活1 10分r1 := []int{0, 1, 0}s1 := ScoreMap{r1, 10}scoreMapList = append(scoreMapList, s1)//活2 100分r2 := []int{0, 1, 1, 0}s2 := ScoreMap{r2, 100}scoreMapList = append(scoreMapList, s2)//活3 1000分r3 := []int{0, 1, 1, 1, 0}s3 := ScoreMap{r3, 1000}scoreMapList = append(scoreMapList, s3)//活4 10000分r4 := []int{0, 1, 1, 1, 1, 0}s4 := ScoreMap{r4, 10000}scoreMapList = append(scoreMapList, s4)//五连 100000分r5 := []int{1, 1, 1, 1, 1}s5 := ScoreMap{r5, 100000}scoreMapList = append(scoreMapList, s5)//死2 10分r6 := []int{0, 1, 1, -1}s6 := ScoreMap{r6, 10}scoreMapList = append(scoreMapList, s6)r7 := []int{-1, 1, 1, 0}s7 := ScoreMap{r7, 10}scoreMapList = append(scoreMapList, s7)//死3 100分r8 := []int{-1, 1, 1, 1, 0}s8 := ScoreMap{r8, 10}scoreMapList = append(scoreMapList, s8)r9 := []int{0, 1, 1, 1, -1}s9 := ScoreMap{r9, 10}scoreMapList = append(scoreMapList, s9)//死4 1000分r10 := []int{-1, 1, 1, 1, 1, 0}s10 := ScoreMap{r10, 10}scoreMapList = append(scoreMapList, s10)r11 := []int{0, 1, 1, 1, 1, -1}s11 := ScoreMap{r11, 10}scoreMapList = append(scoreMapList, s11)//对手情况再copy一遍scoreMapList2 := []ScoreMap{}for _, scoreMap := range scoreMapList {newScoreMap := ScoreMap{}deepCopy(newScoreMap, scoreMap)newScoreMap.score = -scoreMap.scorefor _, v := range scoreMap.role {newScoreMap.role = append(newScoreMap.role, -v)}scoreMapList2 = append(scoreMapList2, newScoreMap)}return append(scoreMapList, scoreMapList2...)
}func eval(chess [][]int, scoreMapList []ScoreMap, step int) int {/*评估当前局势分数*/total++sum := 0//对于每一行进行评估,从上到下,从左往右//行,模拟从上到下for i := 0; i < step; i++ {//列,模拟从左到右for j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > step {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i][j+k] {isOk = falsebreak}}//if j == 1 {//  fmt.Println(scoreMap.role)//}if isOk {sum += scoreMap.score}}}}//对每一列进行评估//列for i := 0; i < step; i++ {//行for j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > step {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//自左上到右下遍历//行for i := 0; i < step; i++ {//列l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > l || i+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//列for i := 0; i < step; i++ {//行l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > l || i+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i+k][j+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//自右上到左下遍历//列for i := 0; i < step; i++ {//行l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if i < len(scoreMap.role) || j+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i-k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//行for i := 0; i < step; i++ {//列l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if i < len(scoreMap.role) || j+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i-k][j+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}return sum
}

极大极小算法


这是一个最简单的博弈树,深度为3,max层代表自己要下的地方,min层代表对方要走的地方。图中博弈树最终生成4种局面,每一种局面的分数分别为76,4,56,45。第二层为min层,对于min层而言,肯定希望局面对对方更有利,于是min层就会选择分数最少的来走。


第一层为max层,max层为自己要走的棋,肯定希望分数越大越好,于是就有了以下的极大极小搜索树。

根据分数的大小,我方就可以选择分数最大的地方进行落子。

alpha-beta剪枝

Alpha Beta 剪枝算法的基本依据是:棋手不会做出对自己不利的选择。依据这个前提,如果一个节点明显是不利于自己的节点,那么就可以直接剪掉这个节点。
具体见:https://blog.csdn.net/lihongxun945/article/details/50668253

下面是极大极小算法go语言实现:

func min(chess [][]int, scoreMapList []ScoreMap, nowDeep int, maxDeep int, step int, resList *ResList, alpha int, beta int) int {/*极小值*/if nowDeep > maxDeep {return eval(chess, scoreMapList, step)}res := Res{score: 99999999, x: 0, y: 0, deep: nowDeep}heuristicsList := heuristicsMin(chess, scoreMapList, step)for _, v := range heuristicsList {i := v.xj := v.ychess[j][i] = -1if res.score < alpha {alpha = res.score}score := max(chess, scoreMapList, nowDeep+1, maxDeep, step, resList, alpha, beta)chess[j][i] = 0if score < res.score {res.score = scoreres.x = ires.y = j}if score < beta { //AB剪枝abc++break}}return res.score
}func max(chess [][]int, scoreMapList []ScoreMap, nowDeep int, maxDeep int, step int, resList *ResList, alpha int, beta int) int {/*极大值*/if nowDeep > maxDeep {return eval(chess, scoreMapList, step)}res := Res{score: -99999999, x: 0, y: 0, deep: nowDeep}heuristicsList := heuristicsMax(chess, scoreMapList, step)for _, v := range heuristicsList {i := v.xj := v.ychess[j][i] = 1if res.score > beta {beta = res.score}score := min(chess, scoreMapList, nowDeep+1, maxDeep, step, resList, alpha, beta)//if nowDeep == 0 {//   fmt.Println(score)//}chess[j][i] = 0if score > res.score {res.score = scoreres.x = ires.y = j}if score > alpha { //AB 剪枝abc++break}}if nowDeep == 0 {resList.resList = append(resList.resList, res)}return res.score
}

启发式搜索

极大极小搜索算法与在alpha-beta剪枝的实现采用前序遍历的方式,所以如果将分数高的节点提前,那么剪枝的效率就越高。于是就有了启发式函数。
参考:https://blog.csdn.net/lihongxun945/article/details/50668622

func heuristicsMax(chess [][]int, scoreMapList []ScoreMap, step int) []Res {heuristicsList := []Res{}for i := 0; i < step; i++ {for j := 0; j < step; j++ {if chess[j][i] == 0 {if !isHavePiece(chess, i, j, n, step) {continue}chess[j][i] = 1score := eval(chess, scoreMapList, step)chess[j][i] = 0heuristicsList = append(heuristicsList, Res{score, i, j, 0})}}}sort.Sort(HeuristicsListMax(heuristicsList))return heuristicsList
}func heuristicsMin(chess [][]int, scoreMapList []ScoreMap, step int) []Res {heuristicsList := []Res{}for i := 0; i < step; i++ {for j := 0; j < step; j++ {if chess[j][i] == 0 {if !isHavePiece(chess, i, j, n, step) {continue}chess[j][i] = -1score := eval(chess, scoreMapList, step)chess[j][i] = 0heuristicsList = append(heuristicsList, Res{score, i, j, 0})}}}sort.Sort(HeuristicsListMin(heuristicsList))return heuristicsList
}

对于当前局势先做一轮初步判断,将分数进行排序。

代码实现

以下是最终AI算法的代码实现,

  • 输入为test.txt文件,保存棋盘信息,0代表空,1代表AI方子位,-1代表对手子位
  • 输出为resList,为切片,从左往右代表每一深度AI的思考落子结果以及分数,total代表调用评估函数次数,abc代表剪枝次数

输入:

输出:

package mainimport ("bufio""encoding/json""fmt""io""os""sort""strconv""strings"
)const n = 1var abc = 0
var total = 0type ScoreMap struct {role  []intscore int
}type Res struct {score intx     inty     intdeep  int
}type HeuristicsListMax []Res
type HeuristicsListMin []Resfunc (h HeuristicsListMax) Len() int {return len(h)
}func (h HeuristicsListMax) Less(i, j int) bool {return h[i].score > h[j].score
}func (h HeuristicsListMax) Swap(i, j int) {h[i], h[j] = h[j], h[i]
}func (h HeuristicsListMin) Len() int {return len(h)
}func (h HeuristicsListMin) Less(i, j int) bool {return h[i].score < h[j].score
}func (h HeuristicsListMin) Swap(i, j int) {h[i], h[j] = h[j], h[i]
}type ResList struct {resList []Res
}// 泛型深拷贝func deepCopy(dst, src interface{}) {bytes, _ := json.Marshal(src)_ = json.Unmarshal(bytes, dst)
}func InitScoreMapList() []ScoreMap {scoreMapList := []ScoreMap{}//活1 10分r1 := []int{0, 1, 0}s1 := ScoreMap{r1, 10}scoreMapList = append(scoreMapList, s1)//活2 100分r2 := []int{0, 1, 1, 0}s2 := ScoreMap{r2, 100}scoreMapList = append(scoreMapList, s2)//活3 1000分r3 := []int{0, 1, 1, 1, 0}s3 := ScoreMap{r3, 1000}scoreMapList = append(scoreMapList, s3)//活4 10000分r4 := []int{0, 1, 1, 1, 1, 0}s4 := ScoreMap{r4, 10000}scoreMapList = append(scoreMapList, s4)//五连 100000分r5 := []int{1, 1, 1, 1, 1}s5 := ScoreMap{r5, 100000}scoreMapList = append(scoreMapList, s5)//死2 10分r6 := []int{0, 1, 1, -1}s6 := ScoreMap{r6, 10}scoreMapList = append(scoreMapList, s6)r7 := []int{-1, 1, 1, 0}s7 := ScoreMap{r7, 10}scoreMapList = append(scoreMapList, s7)//死3 100分r8 := []int{-1, 1, 1, 1, 0}s8 := ScoreMap{r8, 10}scoreMapList = append(scoreMapList, s8)r9 := []int{0, 1, 1, 1, -1}s9 := ScoreMap{r9, 10}scoreMapList = append(scoreMapList, s9)//死4 1000分r10 := []int{-1, 1, 1, 1, 1, 0}s10 := ScoreMap{r10, 10}scoreMapList = append(scoreMapList, s10)r11 := []int{0, 1, 1, 1, 1, -1}s11 := ScoreMap{r11, 10}scoreMapList = append(scoreMapList, s11)//对手情况再copy一遍scoreMapList2 := []ScoreMap{}for _, scoreMap := range scoreMapList {newScoreMap := ScoreMap{}deepCopy(newScoreMap, scoreMap)newScoreMap.score = -scoreMap.scorefor _, v := range scoreMap.role {newScoreMap.role = append(newScoreMap.role, -v)}scoreMapList2 = append(scoreMapList2, newScoreMap)}return append(scoreMapList, scoreMapList2...)
}func ReadChessFromFile(filepath string, step int) [][]int {/*从文件获取棋盘信息*/fi, _ := os.Open(filepath)r := bufio.NewReader(fi)chess := make([][]int, step)j := 0for {lineBytes, err := r.ReadBytes('\n')line := strings.Split(strings.TrimSpace(string(lineBytes)), " ")for i := 0; i < step; i++ {num, _ := strconv.Atoi(line[i])chess[j] = append(chess[j], num)}j++if err == io.EOF {break}}return chess
}func isHavePiece(chess [][]int, x int, y int, n int, step int) bool {/*n格之内是否有棋子*/xMin := x - nxMax := x + nyMin := y - nyMax := y + nif xMin < 0 {xMin = 0}if xMax > step-1 {xMax = step - 1}if yMin < 0 {yMin = 0}if yMax > step-1 {yMax = step - 1}for i := xMin; i <= xMax; i++ {for j := yMin; j <= yMax; j++ {if chess[j][i] != 0 {return true}}}return false}func min(chess [][]int, scoreMapList []ScoreMap, nowDeep int, maxDeep int, step int, resList *ResList, alpha int, beta int) int {/*极小值*/if nowDeep > maxDeep {return eval(chess, scoreMapList, step)}res := Res{score: 99999999, x: 0, y: 0, deep: nowDeep}heuristicsList := heuristicsMin(chess, scoreMapList, step)for _, v := range heuristicsList {i := v.xj := v.ychess[j][i] = -1if res.score < alpha {alpha = res.score}score := max(chess, scoreMapList, nowDeep+1, maxDeep, step, resList, alpha, beta)chess[j][i] = 0if score < res.score {res.score = scoreres.x = ires.y = j}if score < beta { //AB剪枝abc++break}}return res.score
}func max(chess [][]int, scoreMapList []ScoreMap, nowDeep int, maxDeep int, step int, resList *ResList, alpha int, beta int) int {/*极大值*/if nowDeep > maxDeep {return eval(chess, scoreMapList, step)}res := Res{score: -99999999, x: 0, y: 0, deep: nowDeep}heuristicsList := heuristicsMax(chess, scoreMapList, step)for _, v := range heuristicsList {i := v.xj := v.ychess[j][i] = 1if res.score > beta {beta = res.score}score := min(chess, scoreMapList, nowDeep+1, maxDeep, step, resList, alpha, beta)//if nowDeep == 0 {//   fmt.Println(score)//}chess[j][i] = 0if score > res.score {res.score = scoreres.x = ires.y = j}if score > alpha { //AB 剪枝abc++break}}if nowDeep == 0 {resList.resList = append(resList.resList, res)}return res.score
}func eval(chess [][]int, scoreMapList []ScoreMap, step int) int {/*评估当前局势分数*/total++sum := 0//对于每一行进行评估,从上到下,从左往右//行,模拟从上到下for i := 0; i < step; i++ {//列,模拟从左到右for j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > step {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i][j+k] {isOk = falsebreak}}//if j == 1 {//  fmt.Println(scoreMap.role)//}if isOk {sum += scoreMap.score}}}}//对每一列进行评估//列for i := 0; i < step; i++ {//行for j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > step {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//自左上到右下遍历//行for i := 0; i < step; i++ {//列l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > l || i+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//列for i := 0; i < step; i++ {//行l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if j+len(scoreMap.role) > l || i+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i+k][j+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//自右上到左下遍历//列for i := 0; i < step; i++ {//行l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if i < len(scoreMap.role) || j+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[j+k][i-k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}//行for i := 0; i < step; i++ {//列l := step - ifor j := 0; j < step; j++ {for _, scoreMap := range scoreMapList {if i < len(scoreMap.role) || j+len(scoreMap.role) > l {continue}isOk := truefor k := 0; k < len(scoreMap.role); k++ {if scoreMap.role[k] != chess[i-k][j+k] {isOk = falsebreak}}if isOk {sum += scoreMap.score}}}}return sum
}func heuristicsMax(chess [][]int, scoreMapList []ScoreMap, step int) []Res {heuristicsList := []Res{}for i := 0; i < step; i++ {for j := 0; j < step; j++ {if chess[j][i] == 0 {if !isHavePiece(chess, i, j, n, step) {continue}chess[j][i] = 1score := eval(chess, scoreMapList, step)chess[j][i] = 0heuristicsList = append(heuristicsList, Res{score, i, j, 0})}}}sort.Sort(HeuristicsListMax(heuristicsList))return heuristicsList
}func heuristicsMin(chess [][]int, scoreMapList []ScoreMap, step int) []Res {heuristicsList := []Res{}for i := 0; i < step; i++ {for j := 0; j < step; j++ {if chess[j][i] == 0 {if !isHavePiece(chess, i, j, n, step) {continue}chess[j][i] = -1score := eval(chess, scoreMapList, step)chess[j][i] = 0heuristicsList = append(heuristicsList, Res{score, i, j, 0})}}}sort.Sort(HeuristicsListMin(heuristicsList))return heuristicsList
}//func beginGame(chess [][]int) {//  scoreMapList := InitScoreMapList()
//  //fmt.Println(scoreMapList)
//  //num := eval(chess, scoreMapList, 15)
//  //fmt.Println(num)
//  resList := ResList{resList: []Res{}}
//  for i := 0; i < 10; i++ {//      max(chess, scoreMapList, 0, i, 15, &resList, 999999999, -999999999)
//      fmt.Println(resList, total, abc)
//  }
//}func main() {chess := ReadChessFromFile("./test.txt", 15)//fmt.Println(chess)scoreMapList := InitScoreMapList()fmt.Println(scoreMapList)num := eval(chess, scoreMapList, 15)fmt.Println(num)resList := ResList{resList: []Res{}}for i := 0; i < 10; i++ {max(chess, scoreMapList, 0, i, 15, &resList, 999999999, -999999999)fmt.Println(resList, total, abc)}
}

Go语言实现AI五子棋智能算法相关推荐

  1. c语言五子棋人工智能算法,五子棋人工智能算法实现研究,优化五子棋智能算法的思路...

    五子棋是一种两人对弈的纯策略型棋类游戏,是起源于中国古代的传统黑白棋种之一.现代五子棋日文称之为"连珠",英译为"Renju",英文称之为"Goban ...

  2. 五子棋智能算法——决策树编程实现(三)

    上一篇博客(https://blog.csdn.net/viafcccy/article/details/90724073)完成了对于决策树的数据处理 下面我们来建立决策树 和上篇博客一样还是这些属性 ...

  3. 五子棋游戏AI智能算法设计

    五子棋游戏C语言AI智能算法设计 近来发现编制五子棋游戏很有趣,尤其是AI智能算法很烧脑.网上介绍有什么贪心算法,剪枝算法,博弈树算法等等,不一而足. 对于人机对战的电脑智能应子算法,参阅很多五子棋书 ...

  4. 基于C的α-β剪枝算法实现的AI五子棋游戏

    源码下载 http://www.byamd.xyz/hui-zong-1/ 对抗问题 对抗问题:顾名思义,博弈双方是带有对抗性质的.博弈的任何一方都希望局面尽量对自己有利,同时局面也应该尽量令对方不利 ...

  5. AI医疗智能问答算法赛,超二十万大奖等你来拿

    纯粹的算法编程竞赛, AI医疗智能问答算法赛正式启动! 丰厚奖项大量GPU资源,有点给力. 挑战难题大佬带路,可带劲啦! 编程爱好者们, 属于你们的舞台已经准备好啦! ▋什么是AI医疗智能问答 24× ...

  6. EasyNVR智能云终端接入AI视频智能分析功能,用户可自定义接入自己的分析算法

    视频分析的需求 人工智能的发展和在行业中的作用就不用多说了,已经到了势在必行的一个程度了,尤其是对于流媒体音视频行业来说,这基本上是人工智能重中之重的领域,视频人工智能,也就是视频视觉分析的应用方式大 ...

  7. 黑码定制-2019创新研发AI智能算法,大数据量体是时尚的新风口?

    2019年最热的词无疑是5G.AI.人工智能等等-- 随着5G和人工智能的科技发展和普及程度,慢慢的会融入我们的日常生活中, 甚至会改变我们原有的生活方式,这就是一种趋势. 现在很多企业都在研发AI智 ...

  8. 【人工智能】基于蒙特卡洛树搜索和策略价值网络的AI五子棋算法设计

    基于蒙特卡洛树搜索和策略价值网络的AI五子棋算法设计 摘要 蒙特卡洛树搜索算法 五子棋博弈的状态价值函数 附1:详细论文说明下载: 附2:实现代码下载(2022.10更新后代码): 摘要 随着人工智能 ...

  9. 智能算法把奥巴马识别成白人,AI也学会歧视了?

    在人工智能愈发普及的当下,越来越多的地铁.商场或其他公共场所,都已出现了人脸识别的仪器. 按理说,这样先进的技术,本该让人们的生活更便捷,更自由.然而,在某些时候,这些技术非但没能造福人类,反而揭开了 ...

最新文章

  1. Storage Options
  2. UA MATH566 统计理论2 点估计基础
  3. 【Paper】2004_Information Flow and Cooperative Control of Vehicle Formations
  4. html背景自动换,html页面换皮肤颜色、背景图片(更换页面背景,常驻缓存)刷新保存...
  5. 如何把apdu[decode_len]打印出来
  6. Android消息处理机制(Handler、Looper、MessageQueue与Message)
  7. 调用DM FLDR JNI导出数据库文件
  8. SIFT算法中概念简单解释
  9. visual studio code(vscode)的使用(快捷键)
  10. 我的世界服务器权限组权限修改器,我的世界op权限组指令是什么 op权限组指令汇总...
  11. 山东联通中兴B860 AV1.1机顶盒 刷机问题解决
  12. F2FS文件系统论文解读
  13. 文本去重算法:Minhash/Simhash/Klongsent
  14. 卡在硬盘启动计算机,插硬盘启动卡死了,怎么办?电脑维修方法
  15. JAVA流的使用(复制文件效率对比)初学者
  16. 计算特征根时出现复数 ComplexWarning: Casting complex values to real discards the imaginary part
  17. c语言用十年算入门,初识C语言_十年饮冰 难凉热血的技术博客_51CTO博客
  18. 白嫖我珍藏已久的在线小工具【第一弹】
  19. [转] 肾有多好人就有多年轻
  20. 4种大文件传输工具和软件,用于共享大文件

热门文章

  1. Unity3d项目入门之Rolling Ball
  2. [Unity]滑动条与图片填充与滑动条填充(滑动条和Image的关联)
  3. 如何给U盘,SD卡加密(压缩加密与veracrypt加密)
  4. Linux的ioctl和fcntl
  5. Pinia 上手指南 -- 新一代状态管理工具,它会成为 Vuex 的良好替代品吗?
  6. 互联网高薪职业3D建模师到底是什么?游戏建模很赚钱吗?
  7. PAT (Advanced Level) Practice A1090 Highest Price in Supply Chain (25 分)(C++)(甲级)(树,深度)
  8. 你的房间总是一团乱吗?
  9. 非线性光纤光学中分步傅里叶算法(SSFFT)的matlab代码实现
  10. word/latex插入矢量图并导出为pdf