文章目录

  • 前言
  • 一、“吃子”和“气”
    • 1.“吃子”和“气”的概念
    • 2.问题转化
  • 二、深度优先搜索
    • 1.表示方法
    • 2.深度优先搜索
  • 三、提子
    • 1.有无“气”判断
    • 2.提掉无“气”的子
    • 3.对于特殊情形的改进
  • 四、游戏实现
  • 总结

前言

“吃子”是围棋最基本的规则之一,但在编写围棋游戏要如何实现?深度优先搜索可以解决这个问题。本文分享的是个人使用深度优先搜索算法及python语言实现“吃子”的围棋程序,文章中提到的部分词语可能不是围棋的专业术语,只是个人理解的表达,有不妥的地方欢迎批评指正。


以下是本篇文章的正文内容,仅供参考

一、“吃子”和“气”

1.“吃子”和“气”的概念

围棋中,假设己方棋子把对方棋子的“气”全部围住后可以把对方的棋子从棋盘中提走,这就是围棋的“吃子”,也称“提子”。

“吃子”的关键是对棋子进行有无“气”的判断。

“气”,是指在棋盘上与棋子相邻的空交叉点(图一)。


此时黑子显然是有“气”的,但这只是单个棋子的情形,对于更一般的情形(图二)该如何判断呢?


假设现在是黑子的回合,不难看出,这一团白棋在A处还有一口“气”,但是一团用计算机语言表达并不简单,那么有更简单的思路吗?答案是肯定的。我们可以只考虑单个棋子(图三)。


1)对于棋子A,考虑其四个方向:左边和上边是对方棋子,无“气”;下边是棋盘边框,无“气”;右边是空位置,有“气”。

总结:一个棋子的紧邻的是对方棋子或棋盘边框,则该方向无“气”,紧邻的是空位置,则该方向有“气”。一个棋子至少有一个方向有“气”,则该棋子有“气”。 但是如果与白棋紧邻的是己方棋子呢?

2)对于棋子B,上、下、右方向均无“气”,而左边紧邻的是己方棋子,容易看出左边的己方棋子是有“气”的,于是棋子B也有“气”了,因而棋子B有无“气”是依赖于与其相邻的己方棋子的。

如果棋子B依赖的棋子仍依赖于其他棋子呢?我们会发现这是一个递归问题,于是当一个棋子周围没有直接接触的空位置,但有己方棋子时,对下一个己方棋子作相同的操作,直至找到直接接触的空位置为止。这是一个搜索过程。

2.问题转化

可以这样考虑,以要考察的棋子为迷宫的起点,将对方棋子和棋盘边框看作迷宫的障碍,己方棋子看作迷宫的通路,棋盘上的任何空位置都可看作迷宫的出口。棋子有无“气”问题就转化为了迷宫有无出口的问题(图四)。

二、深度优先搜索

1.表示方法

还是图四的情形,为了简化,现在只用八路棋盘来表示。棋盘上的黑子记为-1,白子记为1,空位置记为0,记录在checkerboard_data列表中。

checkerboard_data = [[ 0,  0,  0,  0,  0,  0,  0, 0],[-1, -1, -1, -1, -1,  1, -1, 0],[ 1,  1, -1,  1,  1,  1, -1, 0],[-1,  1, -1,  1, -1,  1, -1, 0],[ 1,  1,  1,  1, -1,  1,  1, 0],[-1,  1, -1,  1, -1,  1, -1, 0],[-1, -1, -1, -1, -1, -1, -1, 0],[ 0,  0,  0,  0,  0,  0,  0, 0]]

为了避免重复搜索,我们还需要一个visit矩阵来记录走过的位置,走过的位置记为1,没有走过的位置记为0。可以这样初始化:

visit = [[0 for i in range(8)] for j in range(8)]

2.深度优先搜索

深度优先搜索(DFS)是一种连通图的遍历算法,是解决迷宫问题的一种常用方法,步骤是从图的某一顶点V0开始,向某一条路走到底,如果该节点不能满足要求,则退回上一个节点,从另一条路走到底,直至遍历完整个图。

由于只关心棋子有无“气”,即只需知道能否逃出“迷宫”,而不关心“迷宫”的全部路径或者最短路径等问题,故使用深度优先搜索算法能尽可能快的找到“出口”,只需搜索到一个出口,即可立即停止搜索,而无需遍历所有通路,便可认为考察的棋子有“气”。当搜索完所有通路仍搜索不到任何出口,也停止搜索,并认为该棋子无“气”。

先定义一个有无气的标志位isalive_flag。

isalive_flag = 0

接下来定义DFS(x, y)函数,其输入x,y为当前搜索位置的横纵坐标。

1)将visit矩阵的当前位置置1(表示此点已搜索过)。

2)定义四个方向并进行循环;如果该方向是棋盘边框,则跳过continue此方向。

3)对于不是边框的方向,还要判断是否走过,若没走过才能开始搜索;如果该位置是空位置,则考察的棋子有“气”,可以return停止搜索了。

4)如果该方向是对方棋子,跟棋盘边框的操作相同,continue跳过此方向;如果该方向是己方棋子,则递归执行DFS()函数,向此方向移动一格;如果上述条件都不满足,表明所有通路都遍历完且仍未找到“出口”,此时可以停止搜索,并认为棋子无“气”。

def DFS(x, y):visit[x][y] = 1 # 表示此点已经搜索过directions = [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]] # 定义上下左右四个方向for dx, dy in directions:if dx < 0 or dx > 7 or dy < 0 or dy > 7:continue # 如果是边框,跳过此方向elif visit[dx][dy] == 0: # 判断是否此点搜索过if checkerboard_data[dx][dy] == 0:isalive_flag = 1return # 此点为空位置,即原棋子有气,停止搜索elif checkerboard_data[dx][dy] == - checkerboard_data[x][y]:continue # 对方棋子,跳过此方向elif checkerboard_data[dx][dy] == checkerboard_data[x][y]:DFS(dx, dy) # 己方棋子,递归执行# 以上条件都不满足,即所有路径都为死路,该棋子无“气”,停止搜索return

三、提子

1.有无“气”判断

接下来对单个棋子进行有无“气”的判断:

1)先定义清空搜索记录函数。

2)定义判断有无“气”的函数is_alive():定义isalive用于返回,清空搜索记录,执行DFS(),通过有“气”标志位可知棋子有无气,再次清空搜索记录后,返回isalive即可。

# 清空搜索记录
def clear_visit():visit = [[0 for i in range(8)] for j in range(8)]isalive_flag = 0#有无“气”的判断,有气返回1,无气返回0
def is_alive(x, y):isalive = 1 # 用于返回# 清空搜索记录clear_visit()# 执行深度优先搜索DFS(x, y)# 有“气”标志为0,则返回0,否则为1if isalive_flag == 0:isalive = 0# 再次清空搜索记录clear_visit()return isalive

2.提掉无“气”的子

当我们可以判断单个棋子,就可以遍历所有棋子,提起所有无“气”的棋子。

token_list = []
for i in range(8):for j in range(8):# 若当前位置是空,则直接跳过if checkerboard_data[i][j] == 0:continue# 判断该棋子有无“气”elif is_alive(i, j) == 0:# 记录token_list.append([i, j])
# 提掉
for x, y in token_list:checkerboard_data[x][y] = 0

注意要先记录,最后再一次性提掉。如果边搜边提,如图五,根据遍历的顺序,棋子A会先被提走,余下的五个白子就会变为有气,不会被提走。

3.对于特殊情形的改进

接下来讨论两种特殊情形:

情形1. 如果落子于无气点能够立马提掉对方的棋子,则对方的棋子被提掉,自己的棋子仍留在棋盘上。 如图六B子下完后能立即提走三个白子。


情形2. 如果落于无气点不能立即提去对方的棋子,则该点为“禁入点”。 图七A点即为白子的禁入点。

因此图六的情形正确的结果是三个白子被提走,所有黑子留在棋盘上。但根据上文的算法,三个白子和黑子B都符合没有“气”的情形,会一并被提去,这与期望不符。

为了解决这个问题,我们可以做这样的改进:每次下子后才对棋盘进行有无气的判断,并且只对对方棋子进行判断,这样就能避免己方棋子也被误提。这就需要一个记录当前玩家的标志位:

player_flag = -1

这样做是解决了情形1,然而不对己方的棋子进行判断,就无法得知是否有情形2(自杀)问题的出现。

故对对方棋子的提子操作结束后,还需对己方棋子进行有无气的判断,如果仍有无“气”棋子存在,则可断言出现了“自杀”行为。

“提子”操作的完整代码如下:

player_flag = -1
suicide_flag = 0 # 自杀标志def take_out():token_list = [] # “死亡”名单# 遍历整个棋盘for i in range(8):for j in range(8):# 若当前位置是空,则直接跳过if checkerboard_data[i][j] == 0:continue# 判断该棋子有无“气”(只判断对方棋子)elif checkerboard_data[i][j] == player_flag and is_alive(i, j) == 0:# 将无“气”的棋子加入“死亡”名单token_list.append([i, j])# 若名单不为空,则提去名单中的所有棋子(仅对方棋子)if len(token_list) != 0:        for i, j in token_list:checkerboard_data[i][j] = 0# 自杀判定# 对方无“气”棋子全部提走后,对己方棋子进行有无“气”的判断,若己方仍存在无“气”棋子,则判定为自杀行为,自杀标志置1(因只需检测到一个无“气”子即说明是自杀,故无需继续检测,跳出循环)for i in range(8):for j in range(8):if checkerboard_data[i][j] == - player_flag:if is_alive(i, j) == 0:#自杀标志置1suicide_flag = 1break

接下来可以在游戏中实现了。

四、游戏实现

主要用pygame实现,完整代码如下(仅供参考):

# 游戏名称:Go Demo
# 描述:围棋游戏
# 作者:吃草的哥哥哥斯拉
# 功能说明
# 1.下子:鼠标点击
# 2.重启游戏:按下键盘r键或回车键
# 3.放弃下子:按下键盘s键
# 4.退出游戏:按下esc键或点击关闭窗口
import sys
import pygame
from pygame.locals import *
# 启动pygame
pygame.init()
# 创建窗口
screen = pygame.display.set_mode((600, 600))
# 设置标题
pygame.display.set_caption("Go Demo")
# 设定字体
font1 = pygame.font.SysFont('SimHei', 20)
font2 = pygame.font.SysFont('arial', 35)
# 设置颜色
background_color = 150, 180, 150
black = 0, 0, 0
white = 255, 255, 255
circle_color = 0, 0, 0
lines_color = 100, 0, 0
text_color = 50, 0, 0# 在pygame屏幕上打印文字
def print_text(font, x, y, text, color=(0,0,0)):imgText = font.render(text, True, color)screen.blit(imgText, (x, y))# 记录鼠标事件
mouse_x = mouse_y = 0
mouse_up = 0
mouse_up_x = mouse_up_y = 0# 定义围棋类
# =========================================================================
# 类名: Go
# 描述: 9x9围棋游戏
# 可用方法:
# 1) 主游戏方法: play()
#    描述: 围棋主游戏的运行,写在pygame的主循环中
# 2) 下子方法: make_a_move(x, y)
#    描述: x,y分别填入鼠标弹起的坐标mouse_up_x,mouse_up_y即可完成下子
# 3) 获取当前鼠标位置方法: get_mouse_current_position(x, y)
#    描述: x,y分别填入鼠标当前的坐标mouse_x,mouse_y,棋子可跟随鼠标移动
# 4) 重启游戏方法: restart_game()
#    描述: 使用此方法重启游戏(清空棋盘,重置当前玩家)
# 5) 悔棋方法(未实现): take_back_a_move()
#    描述: 使用此方法可悔棋,即全局回退到上一步(最多回退五步)
# 6) 转换玩家: switch_play()
#    描述: 使用此方法强制切换当前玩家
# 已实现功能:
#    下子,切换玩家,提去无“气”的子,防止自杀
# 未实现功能:
#    未实现全局同形再现的判断,未实现点目和胜负判断
#    未实现悔棋功能
#    不能调整棋盘路数,不能调整窗口大小
# =========================================================================
class Go:def __init__(self):# -----------------以下为游戏部分数据域--------------------# 用二维列表表示存储棋盘数据,黑子为-1,白子为1,无子为0self.__checkerboard_data = [[0 for i in range(9)] for j in range(9)]# 当前玩家标志,黑为-1,白为1self.__player_flag = -1# 游戏结束标志self.__game_over = 0# 记录鼠标位置self.__mouse_x = 0self.__mouse_y = 0# 自杀标志self.__suicide_flag = 0# 栈(保存前五步棋局)self.__stack = []# 全局同形再现标志(暂无功能)self.__repeat_flag = 0# ------------------以下为搜索部分数据域-------------------# 存储已搜索过的位置,防止重复搜索self.__visit = [[0 for i in range(9)] for j in range(9)]# 是否有“气”标志self.__isalive_flag = 0# -------------------以下为游戏方法--------------------# 绘制棋盘(私有方法)def __draw_checker(self):# 绘制九路棋盘color = lines_colorline_width = 1rect_pos = 100, 100, 400, 400# 绘制边框pygame.draw.rect(screen, color, rect_pos, line_width * 2)# 绘制内线条for i in range(7):pygame.draw.line(screen, color, (100, 100 + i * 50 + 50), (500, 100 + i * 50 + 50), line_width)for i in range(7):pygame.draw.line(screen, color, (100 + i * 50 + 50, 100), (100 + i * 50 + 50, 500), line_width)# 绘制“天元”和“星”positions = [[300, 300], [200, 200], [200, 400], [400, 200], [400, 400]]for pos in positions:pygame.draw.circle(screen, color, pos, 5, 0)# 获取鼠标当前位置def get_mouse_current_position(self, x, y):self.__mouse_x = xself.__mouse_y = y# 棋子跟随鼠标移动(私有方法)def __chess_follow(self):pos = self.__mouse_x, self.__mouse_yif self.__player_flag == -1:color = blackelif self.__player_flag == 1:color = white# 棋子填充pygame.draw.circle(screen, color, pos, 19, 0)# 棋子边框pygame.draw.circle(screen, circle_color, pos, 20, 2)# 切换玩家def switch_player(self):self.__player_flag = - self.__player_flag# print(self.__player_flag)# 下子方法def make_a_move(self, x, y):# 自杀标志位置0self.__suicide_flag = 0# 全局同形再现标志位置0self.__repeat_flag == 0# 若鼠标在指定区域内点击if x>=75 and x<=525 and y>=75 and y<=525:# 将鼠标事件坐标换算成棋盘行列坐标row = (y - 75) // 50col = (x - 75) // 50if self.__checkerboard_data[row][col] == 0:# 将当前棋局压栈self.__push()# 将下子情况记录在棋盘二维列表中,黑子为-1,白子为1,无子为0self.__checkerboard_data[row][col] = self.__player_flag# 每下一子即切换玩家self.__player_flag = -self.__player_flag# print(self.__checkerboard_data)# 提去没有“气”的子self.__take_out()# 如果自杀self.__if_suicide(row, col)# 如果全局同形再现self.__if_repeat()# 如果自杀(私有方法)def __if_suicide(self, row, col):if self.__suicide_flag == 1:# print("Suicide is not allowed!")# 将自杀的棋子提走self.__checkerboard_data[row][col] = 0# 玩家切换回自杀者self.__player_flag = -self.__player_flag# 压栈(私有方法)def __push(self):self.__stack.append(self.__checkerboard_data)if len(self.__stack) > 5:self.__stack.pop(0)# print(self.__stack)# 悔棋方法(待实现)def take_back_a_move(self):if len(self.__stack) != 0:self.__checkerboard_data = self.__stack.pop()# 全局同形再现(待实现)def __if_repeat(self):if self.__repeat_flag == 1:pass# (*)主游戏方法def play(self):# 绘制棋盘self.__draw_checker()# 游戏是否结束self.__if_game_over()# 打印文本self.__print_texts()# 绘制棋子self.__draw_chesses()# 棋子跟随鼠标移动self.__chess_follow()# 打印文本(私有方法)def __print_texts(self):# 禁着点提示if self.__suicide_flag == 1:print_text(font1, 165, 535, "(禁止自杀)", text_color)# 全局同形再现提示(待实现)# elif self.__repeat_flag == 1:#    print_text(font2, 220, 535, "Repeat is not allowed.", text_color)# 绘制棋子(私有方法)def __draw_chesses(self):# 遍历棋盘二维数组,绘制出棋盘中所有已下子for i in range(9):for j in range(9):if self.__checkerboard_data[i][j] == 0:continueelif self.__checkerboard_data[i][j] == -1:color = blackelif self.__checkerboard_data[i][j] == 1:color = whitepos = j * 50 + 100, i * 50 + 100# 棋子填充pygame.draw.circle(screen, color, pos, 19, 0)# 棋子边框pygame.draw.circle(screen, circle_color, pos, 20, 2)# 重启游戏方法def restart_game(self):self.__game_over = 1# 清空棋盘(私有方法)def __clear_checkerboard(self):self.__checkerboard_data = [[0 for i in range(9)] for j in range(9)]# 如果游戏结束(私有方法)def __if_game_over(self):if self.__game_over == 1:self.__clear_checkerboard()self.__game_over = 0self.__player_flag = -1self.__stack = []# --------------------以下为搜索方法----------------------# 深度优先搜索(私有方法)# 对于单颗棋子有无“气”的判断,可看做从该点开始作为迷宫的起点,与己方棋子看作迷宫的“通路”,将对方棋子和棋盘边框看作迷宫的“障碍”,将棋盘中的任何空位置看作迷宫的“出口”,只要搜索到任何“出口”,该棋子即有“气”,搜索不到任何“出口”,该棋子无“气”# 由于只关心棋子有无“气”,即只需知道能否逃出“迷宫”,而不关心“迷宫”的全部路径或者最短路径等问题,故使用深度优先搜索算法能尽可能快的找到“出口”,从而判断棋子有无“气”def __DFS(self, x, y):# 为避免重复搜索,走过的位置记为1self.__visit[x][y] = 1directions = [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]]# 左,右,上,下四个方向for dx, dy in directions:# 左边是墙 或 右边是墙 或 上边是墙 或 下边是墙,即死路,则跳过此方向if dx < 0 or dx > 8 or dy < 0 or dy > 8:continue# 若此方向没有搜索过,则开始搜索elif self.__visit[dx][dy] == 0:# 此方向没有棋子,可看做迷宫的出口,于是该棋子有“气”,停止搜索if self.__checkerboard_data[dx][dy] == 0:self.__isalive_flag = 1return# 此方向是对方棋子,是死路,跳过此方向elif self.__checkerboard_data[dx][dy] == - self.__checkerboard_data[x][y]:continue# 此方向是己方棋子,即通路,继续递归执行DFSelif self.__checkerboard_data[dx][dy] == self.__checkerboard_data[x][y]:self.__DFS(dx, dy)# 以上条件都不满足,即所有路径都为死路,该棋子无“气”,停止搜索return# 清空搜索记录(私有方法)def __clear_visit(self):self.__visit = [[0 for i in range(9)] for j in range(9)]self.__isalive_flag = 0# 是否有"气"(私有方法)def __is_alive(self, x, y):isalive = 1 # 用于返回# 清空搜索记录self.__clear_visit()# 执行深度优先搜索self.__DFS(x, y)# 有“气”标志为0,则返回0,否则为1if self.__isalive_flag == 0:isalive = 0# 清空搜索记录self.__clear_visit()return isalive# 提掉没有“气”的子(私有方法)def __take_out(self):token_list = [] # “死亡”名单# 遍历整个棋盘for i in range(9):for j in range(9):# 若当前位置是空,则直接跳过if self.__checkerboard_data[i][j] == 0:continue# 判断该棋子有无“气”(只判断对方棋子)elif self.__checkerboard_data[i][j] == self.__player_flag and self.__is_alive(i, j) == 0:# 将无“气”的棋子加入“死亡”名单token_list.append([i, j])# 若名单不为空,则提去名单中的所有棋子(仅对方棋子)if len(token_list) != 0:        for i, j in token_list:self.__checkerboard_data[i][j] = 0# 自杀判定# 对方无“气”棋子全部提走后,对己方棋子进行有无“气”的判断,若己方仍存在无“气”棋子,则判定为自杀行为,自杀标志置1(因只需检测到一个无“气”子即说明是自杀,故无需继续检测,跳出循环)for i in range(9):for j in range(9):if self.__checkerboard_data[i][j] == - self.__player_flag:if self.__is_alive(i, j) == 0:self.__suicide_flag = 1break
# 实例化Go类
go = Go()# pygame主循环
while True:for event in pygame.event.get():# 检测退出if event.type == QUIT:sys.exit()# 检测鼠标事件elif event.type == MOUSEMOTION:mouse_x, mouse_y = event.pos# 获得鼠标当前位置go.get_mouse_current_position(mouse_x, mouse_y)elif event.type == MOUSEBUTTONUP:# 当鼠标左键弹起时,下子mouse_up = event.buttonmouse_up_x, mouse_up_y = event.posgo.make_a_move(mouse_up_x, mouse_up_y) # Go类的下子方法# 检测键盘事件elif event.type == KEYUP:# 按回车重启游戏if event.key in (K_RETURN, K_r):go.restart_game() # Go类的重启游戏方法elif event.key == K_ESCAPE:# esc键退出sys.exit()elif event.key == K_BACKSPACE:# 退格键悔棋go.take_back_a_move()elif event.key == K_s:# s键切换玩家go.switch_player()# 填充背景色screen.fill(background_color)# 文字print_text(font2, 5, 5, "This is a go demo.", (0,0,70))# Go类的主游戏方法go.play()# pygame更新pygame.display.update()

运行结果:


棋子无法落入禁入点,并提示禁止自杀:


总结

游戏可以实现基本的下子、吃子、和禁入点的判断,已经是一个可玩的游戏了,但未实现打劫的判断和点目功能,读者有兴趣可以自行实现,这里提供一些思路:1.打劫:局面会重复出现;2.点目:可以考虑对空格进行有无“气”的判断。这篇文章就到这里,以上未实现的功能我可能还会接着完成,敬请期待。

深度优先搜索及python实现围棋“吃子”相关推荐

  1. python 围棋按照坐标查找棋子_深度优先搜索及python实现围棋“吃子”

    前言 "吃子"是围棋最基本的规则之一,但在编写围棋游戏要如何实现?深度优先搜索可以解决这个问题.本文分享的是个人使用深度优先搜索算法及python语言实现"吃子" ...

  2. python实现深度优先搜索_python中的深度优先搜索算法

    假设我有一个函数,它接受一个输入($x iui$),然后经过一个循环并生成一系列输出($x{I,j}$).然后,每个输出可以再次作为同一函数的输入,从而产生更多的输出($x{i,j,k}$).我试图通 ...

  3. 人工智能学习:python实现迭代加深的深度优先搜索

    人工智能学习:python实现深度优先搜索算法 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN10 python版本:3.5 开发 ...

  4. 迷宫问题 深度优先搜索 广度优先搜索 宽度优先搜索【python】

    文章目录 一.实验内容 二.深度优先搜索和广度优先搜索总结 1.深度优先搜索算法 2.广度优先搜索算法 三.实验代码和用于测试的迷宫 1.实验代码 2.测试迷宫 2.1 maze1.txt 2.2 m ...

  5. 深度优先搜索 python_黄哥Python:图深度优先算法(dfs)

    深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法.沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所在边都己被探寻过,搜索将回溯到发现 ...

  6. 常用算法2 - 广度优先搜索 深度优先搜索 (python实现)

    1. 图 定义:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合. 简单点的说:图由节点和边组成.一 ...

  7. 使用动态规划和深度优先搜索解决TSP问题,python编写

    参考: 1)https://www.jianshu.com/p/a66e3166569b 2)https://www.cnblogs.com/youmuchen/p/6879579.html 一使用动 ...

  8. python深度优先搜索传教士和野人_传教士和野人问题解题思路

    传教士和野人渡河问题 刘宪国050422023 野人过河问题描述如下:有三个传教士和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会有危险 ...

  9. python DFS深度优先搜索及N皇后问题求解

    DFS可谓是算法里的一个大头,不懂DFS都不敢承认自己学过数据结构.今天菜鸡我要逆袭了,先从经典的N皇后问题搞起,试试DFS水深几尺[略加思索] 内容篇幅有点长,不想看我对DFS嗷嗷叫的朋友还是直接去 ...

最新文章

  1. RAD Studio XE2/XE3 官方 ISO 下载地址 (2012-09-05更新)
  2. MavenAnt使用
  3. 修改Spring boot内置的tomcat端口
  4. 用YII实现多重查询(基于tag)
  5. Qt Creator桌面平台
  6. dapr微服务.net sdk入门
  7. linux安装mysql遇到的问题_Linux下安装MySQL5.7及遇到的问题解决方法
  8. linux中线程的挂起与恢复(进程暂停)
  9. LeetCode 20. 有效的括号(栈)
  10. mpvue 初始化微信小程序
  11. 苹果Mac鼠标光标丢失如何找回?
  12. Python数据结构与算法分析(第二版)答案 - 第二章(仅供参考)
  13. 新浪微博java sdk文档_新浪微博开放平台:java SDK介绍及使用说明
  14. python2 与 python3 共存
  15. 计算机辅助绘图 选修,计算机辅助绘图(CAD)教学大纲.doc
  16. 创建html自定义标签,如何为htm创建自定义标签
  17. 百慕大将为金融科技和区块链公司提供新的银行服务
  18. 通过百度站长死链提交需要注意哪些事项?
  19. LQ0198 圆周率【程序填空】
  20. win10定时提醒写日报

热门文章

  1. 极路由X(C526A)刷Openwrt 18.06固件(2021-12-12亲测)
  2. LeetCode 1231. 分享巧克力(极小极大化 二分查找)
  3. 论文阅读-2022.1.7-Don’t be Contradicted with Anything CI-ToD: Towards Benchmarking Consistency for Task
  4. java应届生找工作难吗?
  5. 华为鸿蒙os手机版,华为鸿蒙os2.0系统正式版安装包下载-华为鸿蒙2.0系统手机版v2.0安卓版_289手游网下载...
  6. GPLT练习集L1 25--32
  7. vue .sync 用法
  8. Bootstrap实现的响应式APP下载页面代码
  9. vivo删除的便签怎么恢复,vivo手机便签恢复教学
  10. 看门狗电路 通俗理解