1. introduction
Eight empresses estimate everybody knows what problem is, did not elaborate (do not know Baidu)
The display version mainly depends on vue, so the display and internal logic are separated when writing code, so it's no more difficult than the non display version. The only advantage is that you can try it first, which is more intuitive
I contacted the eight queens question before, but I really began to think about it this afternoon. When I wrote the code, I encountered many holes, whether I dug them or not
After writing, I looked at what I wrote before, and found that I could optimize again, but today I'm too tired
2. Schematic diagram
See below
3. code
See below (a lot of useless code, but it's still that reason. I'm too tired to reorganize it). One thing is better, this code can be used by copying and pasting directly
In other words, just copy the code into a txt file, rename it html, and open it with a browser
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <title>home page</title> <style> #main_zone .table{margin:10px;width: 300px;} #main_zone .table td{width: 50px;} #main_zone .table td input{width:30px;border:none;background-color:transparent;text-align:center;} .btn-cells{margin: 10px;} .print-log{margin: 10px;height: 150px;width:400px;overflow: auto;} </style> </head> <body> <main id="main_zone"> <table class="table table-striped table-bordered table-hover"> <tbody> <tr v-for="(arrFirst,indexFirst) in mainData" > <td v-for="(valSecond,indexSecond) in arrFirst" :style="tdStyle(indexFirst,indexSecond)" @click="toggleQueen(indexFirst,indexSecond)"> {{arrFirst[indexSecond]}} </td> </tr> </tbody> </table> <div class="btn-cells"> <input type="button" value="Reset" class="btn btn-primary" @click="resetChoice()" /> <input type="button" value="Calculation" class="btn btn-success" @click="calcChoice()" /> <input type="button" value="Other" class="btn btn-secondary" @click="otherTest()" /> </div> <div class="print-log"> <p v-for="(log,index) in logs">{{log}}</p> </div> </main> <script> //In order to improve the speed, the next bootstrap plug-in can be put locally: //<link href="../../css/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> var vueMain=new Vue({ el:'#main_zone', data:{ mainData:[ [11,12,13,14,15,16,17,18], [21,22,23,24,25,26,27,28], [31,32,33,34,35,36,37,38], [41,42,43,44,45,46,47,48], [51,52,53,54,55,56,57,58], [61,62,63,64,65,66,67,68], [71,72,73,74,75,76,77,78], [81,82,83,84,85,86,87,88] ], choiceData:[],//Record the node records clicked choiceLog:[],//Next, you can select the logs of node collection, which should always be 1 larger than the length of choiceData (the first one is all nodes) logs:[]//Print the log information, do not worry about it temporarily }, created:function(){ //1. The initialization phase will not change var arr0=[]; for(var i=0;i<8;i++){ for(var j=0;j<8;j++){ arr0.push({x:i,y:j}); } } //console.log(JSON.parse(JSON.stringify(arr0))); this.choiceLog.push(arr0); }, computed:{ }, methods:{ //Current level curLevel:function(){ return this.choiceData.length; }, //td style tdStyle:function(x,y){ var okQueenBc='#5cb85c '; / / Green var fbQueenBc='#d9534f '; / / red var fbOtherBc='#f0ad4e '; / / orange var okOtherBc='white';//white var bc=okOtherBc; if(this.hasQueen(x,y)&&!this.forbidArea(x,y)){ bc=okQueenBc; }else if(this.hasQueen(x,y)&&this.forbidArea(x,y)){ bc=fbQueenBc; }else if(!this.hasQueen(x,y)&&this.forbidArea(x,y)){ bc=fbOtherBc; } return { 'background-color':bc, cursor:'pointer' }; }, //Is there a queen hasQueen:function(x,y){ return this.choiceData.some(function(eachChoice){ return eachChoice.x==x&&eachChoice.y==y; }); }, //Prohibited area forbidArea:function(x,y){ return this.choiceData.some(function(eachChoice){ if(eachChoice.x==x&&eachChoice.y==y){ return false; }else if(eachChoice.x==x||eachChoice.y==y){ return true; }else if(eachChoice.x-x==eachChoice.y-y||eachChoice.x-x==y-eachChoice.y){ return true; } }); }, //There is a forbidden queen hasFbQueen:function(){ var that=this; return this.choiceData.some(function(choice){ return that.hasQueen(choice.x,choice.y)&&that.forbidArea(choice.x,choice.y) }); }, //There are other ok ones (the non-zero situation is not considered for the moment. If it is considered, the calculation efficiency can be improved to some extent, but the logic is more complex) hasOkOther:function(logIndex){ logIndex=logIndex||0; var that=this; return this.choiceLog[logIndex].some(function(eachNode){ return !(that.hasQueen(eachNode.x,eachNode.y)||that.forbidArea(eachNode.x,eachNode.y)); }); }, //Find the next node of a level node and return null if not calcNextNode:function(nodeLv){ var thisNodeLog=this.choiceLog[nodeLv]; if(nodeLv==this.curLevel()){//Find next node if(thisNodeLog.length>0){ return thisNodeLog[0]; }else{ return null; } } var thisNode=this.choiceData[nodeLv]; var thisNodeIndex=parseInt(this.calcNodeIndex(thisNode,thisNodeLog)); if(thisNodeIndex==-1||thisNodeIndex>=thisNodeLog.length-1){ //Returns null when the node cannot be found or is already the last node in the level node collection return null; }else{ // console.log(JSON.stringify(thisNodeLog)); // console.log(thisNodeIndex+1); return thisNodeLog[thisNodeIndex+1]; } }, //Get the index of the node calcNodeIndex:function(thisNode,nodeLog){ for(var i in nodeLog){ var eachNode=nodeLog[i]; if(eachNode.x==thisNode.x&&eachNode.y==thisNode.y){ return i; } } return -1; }, //Calculate other ok nodes according to choiceData calcOtherOkNode:function(){ var that=this; return this.choiceLog[0].filter(function(eachNode){ return !that.hasQueen(eachNode.x,eachNode.y)&&!that.forbidArea(eachNode.x,eachNode.y); }); }, //Flip queen (click event) toggleQueen:function(x,y){ if(this.hasQueen(x,y)){ this.delQueen(x,y); }else{ this.setQueen(x,y); } var that=this; //this.logs.push('current number of Queens: '+ this.choiceData.length+(that.hasFbQueen()?', existing conflict! ':', no conflict! '); }, //Set queen setQueen:function(x,y){ this.choiceData.push({ x:x, y:y }); }, //Remove queen delQueen:function(x,y){ this.choiceData=this.choiceData.filter(function(eachNode){ return !(eachNode.x==x&&eachNode.y==y); }) }, //Try adding queen and updating subsequent logs tryAddQueen:function(newNode,newLevel){ var curLevel=this.choiceData.length;//Current level reached newLevel=newLevel||curLevel;//Add next level by default //1. Do not consider the check node, but also to reduce the logic complexity (otherwise, consider the historical situation rather than the real-time situation) //2. If the level is different, cut data and log for(var i=0;i<curLevel-newLevel;i++){ this.choiceData.pop(); this.choiceLog.pop(); } //3. Add data and log this.choiceData.push(newNode); this.choiceLog.push(this.calcOtherOkNode()); // console.log('try log length:'+this.choiceData.length+','+this.choiceLog.length); }, //Reset resetChoice:function(){ this.choiceData=[]; this.logs=[]; }, //Rollback node settings (only previous levels can be rolled back, otherwise there will be problems) rollbackNode:function(nodeLevel){ if(nodeLevel<0){ console.error('node level <0 !'); return false; } // console.log('rollback level:'+nodeLevel); var nextNode=this.calcNextNode(nodeLevel); // console.log('next node:'+JSON.stringify(nextNode)); if(nextNode==null||typeof(nextNode)==='undefined'){ this.rollbackNode(nodeLevel-1); }else{ this.tryAddQueen(nextNode,nodeLevel); this.autoAddNode(8); } }, //Automatically add nodes according to the level (true if possible, false if not) autoAddNode:function(nodeLevel){ //It's necessary to distinguish whether it's not in the beginning or in the end // if(nodeLv=this.curLevel()+1) {/ / find the next node // if(thisNodeLog.length>0){ // return thisNodeLog[0]; // }else{ // return null; // } // } var nextNode=this.calcNextNode(this.curLevel()); // console.log('next node:'+JSON.stringify(nextNode)); if(nextNode==null||typeof(nextNode)==='undefined'){ if(nodeLevel<0){ console.warning('node level =0 ?'); return; } if(!this.rollbackNode(this.curLevel()-1)){ return ; } }else{ this.tryAddQueen(nextNode); } var that=this; if(this.curLevel()<nodeLevel){ // console.log('curLevel:'+this.curLevel()); setTimeout(function(){ that.autoAddNode(nodeLevel); },10); } }, //lookup calcChoice:function(){ //1. Add level 1 queen this.autoAddNode(8); /* * function dosth(){ * if(ok){ * add * }else{ * rollback * } * } */ // this.tryAddQueen(this.choiceLog[0][0]); // if(this.choiceLog[1].length>0){ // this.tryAddQueen(this.choiceLog[1][0]); // if(this.choiceLog[2].length>0){ // this.tryAddQueen(this.choiceLog[2][0]); // }else{ // this.tryAddQueen(this.choiceLog[1][1],1); // } // }else{ // this.tryAddQueen(this.choiceLog[0][1],0); // } }, //Other tests otherTest:function(){ //this.toggleQueen() console.log(this.hasOkOther()); } }, }); </script> </body> </html>
4. results
I don't know how many asymmetric solutions there are to the eight queens problem. What I'm trying to find out here is this: