使用基本的算法,实现数独游戏的填值
来源:互联网 发布:淘宝网实时销售额 编辑:程序博客网 时间:2024/06/05 15:24
可以实现简单级别的数独填值,经本人验证,目前测试的是难度系数在2.0一下的都没有问题,后面会考虑接入神经网络的自组织学习方法,来实现自动的识别高难度系数的数独计算
# encoding: utf-8"""九宫格算法"""import copy class Numobj(object): def __init__(self): self.num_idx = range(1,82,1) # 所有数独数字的索引 self.num = None # 该索引确定的值 self.dic_num = dict() # 索引所对应的全盘的值 self.ok_num = 0 # 记录自动填写的值的数量 self.small_9_no_can = [] # 其他小九宫空格的不能填数字 # 九宫格所对应的各个编码的索引序列,如下图示例 """ #################### # 11#12#10# # # # ## ## # 21#22#20# # # ## # ## # 01#02#00# ################# """ self.R9key_dic = {'11':[0,1,2,9,10,11,18,19,20], '12':[-1,0,1,8,9,10,17,18,19], '10':[-2,-1,0,7,8,9,16,17,18], '21':[-9,-8,-7,0,1,2,9,10,11], '22':[-10,-9,-8,-1,0,1,8,9,10], '20':[-11,-10,-9,-2,-1,0,7,8,9], '01':[-18,-17,-16,-9,-8,-7,0,1,2], '02':[-19,-18,-17,-10,-9,-8,-1,0,1], '00':[-20,-19,-18,-11,-10,-9,-2,-1,0]} def setNum(self,idx,num): """ 设置索引字典的确定的值 :param idx: 当前的字典索引 :param num: 当前字典索引的值 :return: """ self.dic_num[idx] = num print "idx = %d 填value= %d" % (idx, num) def getNum(self,idx): """ 找到指定索引的值 :param idx: 指定索引 :return: """ # 如果有值,则不需要进行判断,没值才需要判断 if self.dic_num[idx] is not None: return # 获得行和列的并集 # unionlist1:表示idx 所在行,列值的并集 linenum, rownum,union_idx = self.getRCSet(idx,"U") m9list = [] # 小九宫存在数字 mkey = self.R9key_dic[str(linenum%3)+str(rownum%3)] self.small_9_no_can = [] # 此处需要清理一下之前数据 for key in mkey: mvalue = self.dic_num[idx+key] if mvalue is not None: m9list.append(mvalue) if key == 0: continue else: # 得到小九宫中,不能填写的值列表 if mvalue is None: lm_9_other, rm_9_other,union_9_other = self.getRCSet((idx+key),"U") self.small_9_no_can.append(union_9_other) # idx_9_other_union_all = self.getListUnion(idx_9_other_union_all,union_9_other) union_all_idx = self.getListUnion(union_idx,m9list) self.GetNoValue(idx,union_all_idx) def getRCSet(self,idx,flag=None): """ 获得行和列的已知元素集合 :param idx:该元素的索引 :param flag:判断使用并集还是交集 :return:行列元素的集合 """ linenum = (idx-1) / 9 +1 # 当前行号 rlist = [] # 横行的存在数字 rownum = (idx-1) % 9 +1 # 当前列号 clist = [] # 纵行存在数字 for i in xrange(9): rvalue = self.dic_num[((linenum-1)*9 +1 + i)] cvalue = self.dic_num[(rownum + 9 * i)] if rvalue is not None: rlist.append(rvalue) if cvalue is not None: clist.append(cvalue) if flag == "U" or flag is None: # 并集 unionlist = self.getListUnion(rlist,clist) return linenum,rownum,unionlist elif flag == "N": # 交集 insectlist = list(set(rlist).intersection(set(clist))) return insectlist def getListUnion(self,a,b): """ 获取数组的并集 :param a:数组 :param b:数组 :return:a,b数组的并集 """ return list(set(a).union(set(b))) def GetNoValue(self, idx, union_all_idx): """ 提取行,列,小九宫中相同的值,找到没有的1-9的数值,如果大于两个,则废弃,如果有一个,则继续 :param union_all_idx: idx所在的行,列及小九宫所有值得并集 :param idx_9_other_union_all:idx所在小九宫,其他已经存在值得行,列的并集 :return: """ l_novalue = [] # 可填的值列表 if idx == 2: print "union_all_idx = %s" % union_all_idx print "self.small_9_no_can = %s" % self.small_9_no_can # exit(0) # print "union_all_idx = %s" % union_all_idx for i in range(1,10): if i not in union_all_idx: # 所填值不能出现在已知的行,列和小九宫内 l_novalue.append(i) else: continue if len(l_novalue) == 0: print "值已经填错,请检查" exit(0) if len(l_novalue) > 1: # 将该数组的九宫格的所有已知数字的相关数字全部拿出来,再次比较,从中排除可能的选项,从而确定必须填的值 tempvalue = [] cangetvalue = self.getOptimiseVlue(l_novalue,self.small_9_no_can) if cangetvalue is not None: self.setNum(idx,cangetvalue) self.ok_num += 1 pass else: print "when idx =%d ,l_novalue = %s" % (idx,l_novalue) self.setNum(idx,l_novalue[0]) self.ok_num += 1 def getOptimiseVlue(self,waitvalue,l_other_9_no_value): """ 得到一个不确定值得唯一值 :param waitvalue: 等待选择的值列表 :param l_other_9_no_value: 其他小九宫的不能选数值 :return: 唯一可以选填的值 """ if len(waitvalue) == 0: return None else: selectlist = [] # 可选择的值得列表 for objw in waitvalue: canflag = True # 此值是否可用 for i in xrange(len(l_other_9_no_value)): if objw in l_other_9_no_value[i]: continue else: canflag = False break if canflag: selectlist.append(objw) if len(selectlist) == 1: return selectlist[0] else: # print "无法得出需要的值,备选项不满足情况=%s" % selectlist return None def SetInitValue(self,vlist = None): """ 设置初始的九宫格数据 :param vlist: 初始数据 """ if vlist is None: for i in xrange(1,82): self.dic_num[i] = i else: self.dic_num = copy.deepcopy(vlist) self.CompleteInit() def CompleteInit(self): """ 用于补全所有的值,未初始的则补全None :return: """ for i in xrange(1,82): if self.dic_num.has_key(i): continue else: self.dic_num[i] = None def ConvertRC(self,line,row,value): """ 行列转换器 :param line: 行标 :param row: 列表 :param value: 设置的值 :return: """ idx = (line-1) *9 + row self.setNum(idx,value) def getNoneNum(self): """ 得到未填写值得数量 :return: None值得数量 """ noneNum = 0 for i in xrange(1,82): if self.dic_num[i] is None: noneNum += 1 return noneNum if __name__ == "__main__": mytest = Numobj() # level 1 raw_vlist = {1:None,2:None,3:None, 4:None,5:None,6:None, 7:None,8:None,9:None, 10:None,11:None,12:None, 13:None,14:None,15:None, 16:None,17:None,18:None, 19:None,20:None,21:None, 22:None,23:None,24:None, 25:None,26:None,27:None, 28:None,29:None,30:None, 31:None,32:None,33:None, 34:None,35:None,36:None, 37:None,38:None,39:None, 40:None,41:None,42:None, 43:None,44:None,45:None, 46:None,47:None,48:None, 49:None,50:None,51:None, 52:None,53:None,54:None, 55:None,56:None,57:None, 58:None,59:None,60:None, 61:None,62:None,63:None, 64:None,65:None,66:None, 67:None,68:None,69:None, 70:None,71:None,72:None, 73:None,74:None,75:None, 76:None,77:None,78:None, 79:None,80:None,81:None} raw_vlist1 = {1:None,2:None,3:2, 4:6,5:9,6:None, 7:5,8:8,9:None, 10:8,11:None,12:None, 13:None,14:2,15:3, 16:6,17:None,18:None, 19:7,20:None,21:6, 22:4,23:None,24:5, 25:2,26:None,27:None, 28:2,29:None,30:9, 31:None,32:None,33:None, 34:3,35:None,36:None, 37:5,38:None,39:1, 40:3,41:None,42:None, 43:9,44:7,45:8, 46:6,47:3,48:7, 49:8,50:5,51:None, 52:4,53:2,54:1, 55:9,56:None,57:8, 58:None,59:4,60:None, 61:1,62:3,63:2, 64:None,65:6,66:None, 67:None,68:None,69:None, 70:7,71:None,72:9, 73:None,74:2,75:None, 76:9,77:None,78:None, 79:8,80:None,81:6} # level 75 raw_vlist75 = {3:1,7:6,11:5,12:9,15:2,19:4,24:6,27:2,31:8,32:7,35:1,37:2,41:9,45:7, \ 47:4,50:5,51:3,55:8,58:5,63:6,67:1,70:7,71:9,75:4,79:5} mytest.SetInitValue(raw_vlist1) print mytest.dic_num j =0 # 当前计算的轮次 while mytest.getNoneNum()>0: print "当前剩余None的值 = %d" % mytest.getNoneNum() j+=1 print "当前第%d轮猜值" % j for i in xrange(1,82): mytest.getNum(i) print "猜对的值= %d" % mytest.ok_num if j > 100: print "数值有问题,无解!!!" break print "未猜对的None值数量为:%d" % mytest.getNoneNum() for i in xrange(1,82): if (i-1)%9 == 0: print "\n" print mytest.dic_num[i],
0 0
- 使用基本的算法,实现数独游戏的填值
- 数独游戏的生成算法
- 数独游戏的程序算法
- 算法实践:数独的基本解法
- 独数的算法
- 数独算法的java实现
- java实现数独的算法
- 数独游戏的设计
- 算法实践——数独的基本解法
- 使用HTML5的drag&drop做一个数独游戏
- 使用HTML5的drag&drop做一个数独游戏
- 数独的求解算法
- 数独的java实现
- 数独的简单实现
- 关于"数独--九宫格"的算法实现
- 数独问题的一种简单算法代码实现
- Javascript 实现的数独解题算法网页实例
- Javascript 实现的数独解题算法网页实例
- 《数据库索引设计优化》读书笔记(七)
- Smarty 入门一
- [bzoj 2725] 故乡的梦
- TCP客户端
- NodeJS学习
- 使用基本的算法,实现数独游戏的填值
- ISBN编码
- 最大公约数最小公倍数
- test
- USACO 1.1.1 Your Ride Is Here
- 正则表达式
- [BZOJ3942] [Usaco2015 Feb]Censoring
- cvCompareHist() 直方图匹配
- transform属性