很多朋友对于sodu网站源码分享和slay不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!
创作背景
小学的时候玩过数独,在假期里做了好多数独题,初中的时候有一个同学给我发了一个特别难的数独题,是一个数学家出的,还据说有一个农民只花了一天的时间就做出来了。当时那个数独题实在是太难了,做到一定程度就感觉没有线索了。
后来大学之后学了编程,我就在想,可以自己写一个破解数独的程序来,让程序破解数独。于是我就自己想了一种算法,一个一个数字的往下测试,不通过就撤回,不通过就继续测试下一个数,最终破解的方法。
大一结束,疫情时代,暑假在家的时候做的,未参考任何数独破解相关资料就直接埋头做出来的。
效果截图
草稿思路
结果
合影留念
源代码
Java版
importjava.util.ArrayList;\nimportjava.util.Scanner;\n\n/**\n*破解数独的程序,java版\n*此程序要求使用者自己手动写入一个9*9标准数独,然后程序会对其破解\n*2020年7月19日\n*@authorlittlefean\n*/\npublicclassSudoku{\n\npublicstaticvoidmain(String[]args){\nint[][][]sudokuBox=newTemp();\nprintSudoku(sudokuBox);\nstartWrite(sudokuBox);\nprintSudokuWithBorder(sudokuBox);\ncrack(sudokuBox);\nprintSudokuWithBorder(sudokuBox);\n}\n\n/**\n*新创一个数独三维数组,返回这个三维数组\n*数独的数据结构是一个三维数组,\n*其中第一维度是行,\n*第二维度是列,\n*第三维度是这个数的信息,含有两个元素,【数字,是否可写(01表示)】\n*@return返回这个三维数组\n*/\nprivatestaticint[][][]newTemp(){\nint[][][]box=newint[9][9][2];\nfor(inti=0;i<9;i++){\nfor(intj=0;j<9;j++){\nbox[i][j]=newint[]{0,1};\n}\n}\n//System.out.println(Arrays.deepToString(box));\nreturnbox;\n}\n\n/**\n*打印数独三维数组\n*/\nprivatestaticvoidprintSudoku(int[][][]box){\nfor(inti=0;i<3;i++){\nfor(intj=0;j<3;j++){\nfor(intk=0;k<3;k++){\nfor(intm=0;m<3;m++){\nSystem.out.print(box[i*3+j][k*3+m][0]+&34;);\n}\nSystem.out.print(&34;);\n}\nSystem.out.println();\n}\nSystem.out.println();\n}\n}\n\n/**\n*以含有边框的形式打印数独\n*@parambox数独的三维数组\n*/\nprivatestaticvoidprintSudokuWithBorder(int[][][]box){\nSystem.out.println(&34;);\nfor(inti=0;i<3;i++){\nfor(intj=0;j<3;j++){\nSystem.out.print(&34;);\nfor(intk=0;k<3;k++){\nfor(intm=0;m<3;m++){\nSystem.out.print(box[i*3+j][k*3+m][0]+&34;);\n}\nSystem.out.print(&34;);\n}\nif(j!=3-1){\nSystem.out.println();\n}\n}\nif(i!=3-1){\nSystem.out.println(&34;);\n}\n}\nSystem.out.println(&34;);\n}\n\n/**\n*开始出题\n*传入数独数组,并要求用户输入数据对其内容进行修改\n*注意:该函数直接改变了三维数组参数的状态,所以不用返回值\n*注意:该函数没有处理输入异常,用户需要自觉输入整数\n*@parambox空数独\n*\n*/\nprivatestaticvoidstartWrite(int[][][]box){\nScannersc=newScanner(System.in);\nSystem.out.println(&34;);\nSystem.out.println(&34;);\nintnum=sc.nextInt();\nfor(inti=0;i<num;i++){\nSystem.out.print(&34;+i+1+&34;);\nintnumber=sc.nextInt();\nSystem.out.print(&34;);\ninty=sc.nextInt();\nSystem.out.println(&34;);\nintx=sc.nextInt();\nbox[y-1][x-1][0]=number;\nbox[y-1][x-1][1]=0;\n}\nsc.close();\n}\n\n/**\n*判断整个数独是不是合法的,如果是,返回True,反之False。\n*@parambox数独三维数组\n*@return如果是,返回True,反之False\n*/\nprivatestaticbooleanisTrue(int[][][]box){\n//判断所有行\nfor(inti=0;i<9;i++){\n//遍历每一行:\nfor(intj=0;j<9;j++){\n//遍历1-9数字,看是否重复\nintnum=j+1;\nintnumTimes=0;\nfor(intk=0;k<9;k++){\n//遍历一行里的9个位置:\nif(box[i][k][0]==num){\nnumTimes++;\n}\n}\nif(numTimes>1){\nreturnfalse;\n}\n}\n}\n//判断所有列\nfor(inti=0;i<9;i++){\n//遍历每一列:\nfor(intj=0;j<9;j++){\n//遍历1-9数字,看是否超过1:\nintnum=j+1;\nintnumTimes=0;\nfor(intk=0;k<9;k++){\n//遍历一列里的9个位置:\nif(box[k][i][0]==num){\nnumTimes++;\n}\n}\nif(numTimes>1){\nreturnfalse;\n}\n}\n}\n//判断所有宫\nfor(inti=0;i<3;i++){\n//遍历每一行宫\nfor(intj=0;j<3;j++){\n//在每一行宫里遍历每一个宫\nfor(intk=0;k<9;k++){\n//在每一个宫里遍历每一个数字:\nintnum=k+1;\nintnumTimes=0;\nfor(intm=0;m<3;m++){\n//在每一个宫里遍历3行\nfor(intn=0;n<3;n++){\n//在每一个宫的每一行里遍历三个位置:\nif(box[i*3+m][j*3+n][0]==num){\nnumTimes++;\n}\n}\n}\nif(numTimes>1){\nreturnfalse;\n}\n}\n}\n}\nreturntrue;\n}\n\n/**\n*破解数独\n*输入一个数独三维数组,修改数独三维数组的内容使其成为一个完整的正确的数独三维数组\n*若发现无解则直接退出程序。\n*注意:此函数直接修改了数独的状态\n*@parambox数独三维数组\n*/\nprivatestaticvoidcrack(int[][][]box){\n\n//int[][]writeArray=newint[81][2];\n//writeArray不知道多长,只能用集合表示\nArrayList<int[]>writeArray=newArrayList<>();\nfor(inti=0;i<9;i++){\nfor(intj=0;j<9;j++){\nif(box[i][j][1]==1){\n//在集合中增加box[i][j]这个数\nwriteArray.add(box[i][j]);\n}\n}\n}\nintx=0;\nintn=1;\nwhile(true){\n//writeArray[x][0]=n;编译器说这样不行\n//Arraytypeexpected;found:&39;\nwriteArray.get(x)[0]=n;\nif(isTrue(box)){\nif(x==writeArray.size()-1){\nSystem.out.println(&34;);\nbreak;\n}else{\nx++;\nn=1;\n}\n}else{\nwhile(true){\nif(n>=9){\nif(x==0){\nSystem.out.println(&34;);\nSystem.exit(1);\n}else{\nwriteArray.get(x)[0]=0;\nx–;\nn=writeArray.get(x)[0];\nn++;\n}\n}else{\nn++;\nbreak;\n}\n}\n}\n}\n}\n}
python版
&34;&34;&34;\n\n\ndefnewTemp():\n&34;&34;&34;\narray=[]\nforiinrange(9):\narray.append([])\nforjinrange(9):\narray[i].append([0,True])\nreturnarray\n\n\n34;&34;开始出题&34;&34;请输入初始数的数量:&34;请输入第{i+1}个数&34;您要输入的数字是多少?&34;输入的数字在第几行?&34;第几列?&34;数据输入完毕,开始破解输入1,修改输入数据请输入任意……&39;1&34;您要修改的数字是多少?&34;输入的数字在第几行?&34;第几列?&34;是否开始破解?是请输入1,否则输入任意:&39;1&34;&34;\n传入一个数独二维列表,判断其是否合法,若合法则返回真,否则返回假\n:paramarray:表示数独的二维列表\n:return:\n&34;&判断所有行\nforiinrange(9):\n遍历1-9数字,看是否超过1:\nnum=j+1\nnumTimes=0\nforkinrange(9):\n判断所有列\nforiinrange(9):\n遍历1-9数字,看是否超过1:\nnum=j+1\nnumTimes=0\nforkinrange(9):\n判断所有宫\nforiinrange(3):\ny=i*3\nforjinrange(3):\nx=i*3\nforkinrange(9):\n在每一个宫里遍历3行\n在每一个宫的每一行里遍历三个位置:\nifarray[y][x][0]==num:\nifarray[i*3+m][j*3+n][0]==num:\nnumTimes+=1\nifnumTimes>1:\nreturnFalse\nreturnTrue\n\n\ndefprintSudoku(array):\n&34;&34;&34;\nforiinrange(3):\n三横行紧凑\nforkinrange(3):\n每一个数\nprint(array[i*3+j][k*3+m][0],end=&34;)\nprint(&39;,end=&34;)\nprint()\nprint()\n\n\ndefprintSudokuTable(array):\n&34;&34;&34;\nprint(&34;)\nforiinrange(3):\n每一行\nprint(&39;,end=&34;)\nforkinrange(3):\n每一个数\nprint(array[i*3+j][k*3+m][0],end=&34;)\nprint(&39;,end=&34;)\nifj!=3-1:\nprint(&39;)\nifi!=3-1:\nprint()\nprint(&34;)\nprint()\nprint(&34;)\n\n\ndefcrack(soduArray):\n&34;&34;&34;\n此数组里的对象是数独列表里的对象,所以可以直接引用,同步更改\nwriteArray=[]\nforiinrange(len(soduArray)):\nforjinrange(len(soduArray[i])):\nifsoduArray[i][j][1]:\nwriteArray.append(soduArray[i][j])\nx=0\nn=1\nstep=0\nwhileTrue:\nprint(step)\nprintSudokuTable(soduArray)\n\nwriteArray[x][0]=n\nifisTrue(soduArray):\nstep+=1\nifx==len(writeArray)-1:\nprint(&34;)\nprintSudokuTable(soduArray)\nbreak\nelse:\nx+=1\nn=1\ncontinue\nelse:\nwhileTrue:\nstep+=1\nifn>=9:\nifx==0:\nexit(&34;)\nelse:\nwriteArray[x][0]=0\nx-=1\nn=writeArray[x][0]\nn+=1\ncontinue\nelse:\nn+=1\nbreak\nprint(f&34;)\n\n\nif__name__==&39;:\n34;欢迎使用破解程序,本程序由littlefean于2020年7月18日完成&34;下面进入数独初始状态输入阶段&34;提示:0表示空白位置,如果想删除某个位置的数,可以在输入数字的时候输入0,并覆盖相应的位置&开始出题\nsudoku=startWrite(sudoku)\nprint(isTrue(sudoku))\n\n34;end”)\n
发现
Python破解我那个初中同学发的很难的数独,花了30秒。而java几乎只花了3秒。Java的程序效率比Python的效率高出了很多。
反思与总结
下次我再改进程序的时候,我应该使用面向对象的方法把数独的元素封装起来,把数独写成一个类,方便使用。
肯定有比我的程序更好的算法。我的程序不一定很好。
如果你还想了解更多这方面的信息,记得收藏关注本站。
