利用python抓取网页上的数独,并用回溯法破解

这里抓取的是https://www.oubk.com/上不用登陆就能查看的数独

以下是抓取数独的代码:

class Crawl_shudu(object):
	def __init__(self,url):
		self.url = url

	def start(self):
		response = requests.get(self.url).text
		soup = BS(response,'lxml')
		sdbody = soup.find('table',class_='ptb')

		shudu = []
		for tr in sdbody.find_all('tr'):
			trnum = []
			for td in tr.find_all('td'):
				num = td.find('input')['value']
				if num == '':
					trnum.append(0)
				else:
					trnum.append(int(num))
			shudu.append(trnum)
		return shudu

此代码将网页上的数独返回为一个多元数组,如下


破解思路:

寻找第一个0值,并循环代入(1-9)数值进去,若符合条件(每行每)则寻找下一0值,并继续代值进去尝试,若都不符合,则返回到上一层,代入下一数字尝试,以此方法遍历下去,此方法尝试次数一般需要几万次,但过程不会超过1s

代码如下:

import datetime
import requests
from bs4 import BeautifulSoup as BS

class Fuck_shudu(object):
	def __init__(self,board):
		self.b = board   #数独,方便后面调用
		self.t = 0      #尝试的次数
	
	def check(self,x,y,value):  #测试数独是否符合规则,每行每列每宫数字不重复
		for row_item in self.b[x]:  #每行
			if row_item == value:
				return False
		for row_all in self.b:    #每列
			if row_all[y] == value:
				return False
		row,col = int(x/3)*3,int(y/3)*3   #判断该点属于哪宫
		row3col3 = self.b[row][col:col+3]+self.b[row+1][col:col+3]+self.b[row+2][col:col+3]
		for row3col3_item in row3col3:
			if row3col3_item == value:
				return False
		return True
	
	def get_next(self,x,y):  #得到下一个0点
		for next_soulu in range(y+1,9):
			if self.b[x][next_soulu] == 0:
				return x,next_soulu
		for row_n in range(x+1,9):
			for col_n in range(0,9):
				if self.b[row_n][col_n] == 0:
					return row_n,col_n
		return -1,-1
	
	def try_it(self,x,y): #破解函数,遍历每个0值,并循环填入值,尝试是否符合规则
		if self.b[x][y] == 0:
			for i in range(1,10):
				self.t += 1
				if self.check(x,y,i): #如果i符合,尝试设置(x,y) = i
					self.b[x][y] = i
					next_x,next_y = self.get_next(x,y) #得到下一0值的坐标
					if next_x == -1: #后面没有0值,破解成功
						return True
					else:
						end = self.try_it(next_x,next_y) #迭代,尝试填下一值
						if not end:  #not end 说明(x,y) = i 不符合
							self.b[x][y] = 0 #重新将(x,y)设置为0,并测试下一个i值是否符合条件
						else:
							return True
	
	def start(self):
		begin =datetime.datetime.now()
		if self.b[0][0] == 0:
			self.try_it(0,0)
		else:
			x,y = self.get_next(0,0)
			self.try_it(x,y)
		for i in self.b:
			print(i)
		end = datetime.datetime.now()
		print('cost time:{}'.format(end-begin)) #花费的时间(一般不会超过1s)和总次数
		print('try sum times:{}'.format(self.t))




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值