Swift数独游戏优化——C++与OC混编、plist自动生成
一、为什么要C++与OC混编?
在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的。
但是在我的例子中我发现这样存在一定的局限性:
1、我是利用Terminal的重定向功能来实现输出的,这样不能查看程序的实际运行状态信息。
2、C++编写的代码不能直接生成plist文件,而OC有直接的API可以生成plist文件。(当我前几天刚知道的时候我感觉之前用C++生成plist是有多勇敢)
二、如何进行C++与OC混编?
1、OC文件后缀改为“mm”
2、混编下涉及OC的语法要写在 “#import <Foundation/Foundation.h>”之后
三、注意点:
关于OC开发中的文件后缀名区别m,mm,cpp,h
1)文件区别:
.h :头文件。头文件包含类,类型,函数和常数的声明。
.m :源代码文件。这是典型的源代码文件扩展名,可以包含Objective-C和C代码。
.mm :源代码文件。带有这种扩展名的源代码文件,除了可以包含Objective-C和C代码以外还可以包含C++代码。仅在你的Objective-C代码中确实需要使用C++类或者特性的时候才用这种扩展名
.cpp:只能编译C++
当你需要在源代码中包含头文件的时候,你可以使用标准的#include编译选项,但是Objective-C提供了更好的方法。#import选项和#include选项完全相同,只是它可以确保相同的文件只会被包含一次。Objective-C的例子和文档都倾向于使用#import。
.m 和.mm 的区别是告诉gcc 在编译时要加的一些参数。当然.mm还可以命名成.m,但在编译时要手动加参数(麻烦)
2)常用场景:
如果你的OC代码里面有包含C++的引用或代码,将此类更改为.mm即可;
3)例子:
ERROR:./zxing/cpp/core/src/zxing/common/Counted.h:21:10: 'iostream' file not found
在引用zxing的时候#import<QRCodeReader.h>用到了iostream,但是它是/iphoneOS6.1/user/include/c++下面的类,故需要把类名改为.mm即可
注意#import或#include的位置要在.mm文件里,如果在.h头文件里是没用的
四、具体到数独游戏的例子,最后的混编代码如下:
main.mm
1: //
2: // main.m
3: // sudokuGenerater
4: //
5: // Created by 张泽阳 on 4/9/15.
6: // Copyright (c) 2015 张泽阳. All rights reserved.
7: //
8:
9:
10: #include <fstream>
11: #include <unistd.h>
12: #include "stdio.h"
13: #include "stdlib.h"
14: #include "time.h"
15: //#include "fstream.h"
16: #include <iostream>
17: #include <sstream>
18: #include <string>
19:
20: using namespace std;
21: ostringstream oss;
22: ostringstream coutt;
23: string currentS;
24: class CSudoku
25: {
26: int map[9][9],lastmap[9][9];
27: int smod;
28: int solves;
29: int check(int,int,int*);
30: void dfs();
31: public:
32: enum{ANY=0,ALL=1};
33: CSudoku(int n=40);// 随机生成数独,n越大越难
34: CSudoku(int *data);// 人工指定数独
35:
36: string display();// 显示数独
37: void Sdisplay();// 显示数独
38: int resolve(int mod=ALL);// 解数独
39: };
40: long sand=0;
41:
42:
43: CSudoku::CSudoku(int n)
44: {
45: int i,j;
46: sand++;
47: srand(time(&sand));
48: do
49: {
50: for(i=0;i<9;++i)
51: {
52: for(j=0;j<9;++j)
53: map[i][j]=0;
54: j=rand()%9;
55: map[i][j]=i+1;
56: }
57: }
58: while(!resolve(ANY));
59:
60: // 挖窟窿
61: for(int k=0;k<n;)
62: {
63: i=rand()%81;
64: j=i%9;
65: i=i/9;
66: if(map[i][j]>0)
67: {
68: map[i][j]=0;
69: ++k;
70: }
71:
72: }
73: //printf("(randomized sudoku created with %d blanks.)\n",blanks);
74: }
75: CSudoku::CSudoku(int *data)
76: {
77: int *pm=(int*)map;
78: for(int i=0;i<81;++i)
79: pm[i]=data[i];
80: }
81: void addS();
82: string CSudoku::display()
83: {
84: ostringstream osst;
85: osst.str("");
86: // osst<<"<string>";
87: for(int i=0;i<9;++i)
88: {
89: for(int j=0;j<9;++j)
90: {
91: // if(map[i][j]>0)
92: // printf("< %d > ",map[i][j]);
93: // else
94: // printf("[ ] ");
95:
96: osst<<map[i][j];
97: }
98: // printf("\n");
99: }
100: // osst<<"</string>\n";
101: // oss<<osst.str();
102: return osst.str();
103: }
104: int same = 1;
105: void sameLog();
106: void CSudoku::Sdisplay()
107: {
108: ostringstream osst;
109: osst.str("");
110: // osst<<"<string>";
111: same = 1;
112: for(int i=0;i<9;++i)
113: {
114: for(int j=0;j<9;++j)
115: {
116: if (map[i][j]!=lastmap[i][j]) {
117: same = 0;
118: }
119: }
120: }
121: if (same) {
122: sameLog();
123: // same = 0;
124: return;
125: }
126: for(int i=0;i<9;++i)
127: {
128: for(int j=0;j<9;++j)
129: {
130: lastmap[i][j] = map[i][j];
131: osst<<map[i][j];
132: }
133: }
134: // osst<<"</string>\n";
135: // oss<<osst.str();
136: currentS = osst.str();
137: addS();
138: }
139: int CSudoku::resolve(int mod)
140: {
141: smod=mod;
142: if(mod==ALL)
143: {
144: solves=0;
145: dfs();
146: return solves;
147: }
148: else if(mod==ANY)
149: {
150: try
151: {
152: dfs();
153: return 0;
154: }
155: catch(int)
156: {
157: return 1;
158: }
159: }
160: return 0;
161: }
162: int CSudoku::check(int y,int x,int *mark)
163: {
164: int i,j,is,js,count=0;
165: for(i=1;i<=9;++i)
166: mark[i]=0;
167: for(i=0;i<9;++i)
168: mark[map[y][i]]=1;
169: for(i=0;i<9;++i)
170: mark[map[i][x]]=1;
171: is=y/3*3;
172: js=x/3*3;
173: for(i=0;i<3;++i)
174: {
175: for(j=0;j<3;++j)
176: mark[map[is+i][js+j]]=1;
177: }
178: for(i=1;i<=9;++i)
179: if(mark[i]==0)
180: count++;
181: return count;
182: }
183: int toomanys = 0; int blanks = 40;
184: void CSudoku::dfs()
185: {
186: int i,j,im=-1,jm=0,min=10;
187: int mark[10];
188: for(i=0;i<9;++i)
189: {
190: for(j=0;j<9;++j)
191: {
192: if(map[i][j])
193: continue;
194: int c=check(i,j,mark);
195: if(c==0)
196: return;
197: if(c<min)
198: {
199: im=i;
200: jm=j;
201: min=c;
202: }
203: }
204: }
205: if(im==-1)
206: {
207: if(smod==ALL)
208: {
209: ++solves;
210: // printf("No. %d:\n",++solves);
211: if (solves>(2)) {
212: toomanys = 1;
213: return;
214: }
215: Sdisplay();
216: return;
217: }
218: else if(smod==ANY)
219: {
220: throw(1);
221: }
222:
223: }
224: check(im,jm,mark);
225: for(i=1;i<=9;++i)
226: {
227: if(mark[i]==0)
228: {
229: map[im][jm]=i;
230: dfs();
231: }
232: }
233: map[im][jm]=0;
234: }
235:
236:
237: #import <Foundation/Foundation.h>
238: //#import "ref.mm"
239: NSMutableArray* eachSArray ;
240: /**
241: * 混编下涉及OC的语法要写在 “#import <Foundation/Foundation.h>”之后
242: *
243: */
244: void addS(){
245: [eachSArray addObject:[NSString stringWithFormat:@"%s",currentS.c_str()]];
246: }
247: void sameLog(){
248: NSLog(@"same!!!!!!");
249: }
250: int main(int argc, const char * argv[]) {
251: @autoreleasepool {
252: //得到完整的文件名
253: NSString *filename=[@"/Users/zhangzeyang/Desktop/" stringByAppendingString:@"R.plist"];
254: NSMutableDictionary *data = [[NSMutableDictionary alloc]init];
255: int num = 0;
256: while (blanks<71) {
257: NSLog(@"\n------------blanks = %d------------\n",blanks);
258: // coutt<<"<key>D"<<blanks<<"</key>"<<endl<<"<array>"<<endl;
259: NSMutableArray* eachDArray = [[NSMutableArray alloc]init];
260: int inNum = 0;
261: // for (int ii = 0; ii + blanks <120; ++ii) {
262: for (int ii = 0; ii < 34 - blanks / 10; ++ii) {
263: NSLog(@"blanks = %d num = %d ii = %d",blanks,num,ii);
264:
265: same = 1;toomanys = 0;
266: // oss<<"<dict>"<<endl<<"<key>p</key>"<<endl;
267: NSMutableDictionary* eachPassDic = [[NSMutableDictionary alloc]init];
268: CSudoku s(blanks);
269: string ppp = s.display();
270: [eachPassDic setValue:[NSString stringWithFormat:@"%s",ppp.c_str()] forKey:@"p"];
271: eachSArray = [[NSMutableArray alloc]init];
272:
273: // oss<<"<key>s</key>"<<endl<<"<array>"<<endl;
274: s.resolve();
275: // oss<<"</array>"<<endl<<"</dict>"<<endl;
276: if (same){
277: oss.str("");
278: continue;
279: }else{
280: // coutt<<oss.str();
281: oss.str("");
282: [eachPassDic setValue:eachSArray forKey:@"s"];
283: [eachDArray addObject:eachPassDic];
284: ++num;++inNum;
285: }
286: if (inNum>30) {
287: break;
288: }
289: }
290: // coutt<<"</array>"<<endl;
291: if (inNum ) {
292: // cout<<coutt.str();
293: [data setValue:eachDArray forKey:[NSString stringWithFormat:@"D%d",blanks]];
294: }
295: coutt.str("");
296: oss.str("");
297: blanks+=1;
298:
299: }
300:
301: // cout<<"</dict>\n</plist>\n";
302: //输入写入
303: [data writeToFile:filename atomically:NO];
304: }
305: return 0;
306: }
六、涉及到的其他知识
1)string转char*
char* s = str.c_str();
即可
参考链接:
http://blog.csdn.net/totogo2010/article/details/7634185
http://blog.csdn.net/penuel/article/details/9796721
http://www.cnblogs.com/zhixing/archive/2013/06/04/3116814.html