本系列教程将指导大家一步步使用Jquery Mobile设计一个Android的通讯录应用。其中在应用的界面部分,将使用jQuery Mobile框架,并且会指导大家如何使Android中提供的webview浏览器容器控件中的javascript去访问后端JAVA应用程序,以及 后端JAVA应用如何去访问前端的Javascript和HTML。

  本文假设读者已对jQuery Mobile有一定的初步认识,同时也初步了解Android的一些基本用法。关于jQuery Mobile框架的介绍,可以参考如下几篇文章:

  http://tech.it168.com/a2010/1210/1136/000001136835.shtml

  http://tech.it168.com/a2011/0324/1170/000001170077.shtml

  本教程的结构

   本系列教程安排如下。在第一部分中,我们将介绍在应用程序中的运行界面截图,说明整个应用的流程走向及结构,并说明一些如何在Android的 Webview控件中通过Javascript与后端的JAVA应用程序交互的一些技巧和知识点,其中会介绍jQuery Mobile中的各种重要页面元素。在本系列的第二部分中,将介绍如何在通讯录应用中新增加、编辑和删除帐号。在本系列的第三部分中,将介绍如何增加通讯 录,其中会介绍用到一个工具类。在第四部分,将重点介绍如何使用Jackson JSON处理库去将JAVA对象和JSON对象之间进行转换,并介绍了项目整个工程如何配置,如何根据Android的图标设计最佳实践去设计图标,最后 总结全系列的教程。

  页面流程结构

  下面来讲解应用的页面流程结构。在这个应用中,每个通讯录都与帐号相 关联的,也就是说,每个帐号的用户中可以建立多个通讯录,就象gmail一样。当Android应用启动后,会检查应用中是否已经建立了帐号,如果是第一 次启动,是不存在帐号的,那么会提示用户新建立一个帐号,如下图所示:

  一旦建立了帐号后,就可以进入通讯录的初始页面了,如下图:

  可以看到,上图是按字母顺序对通讯录排序。当用户点“Add”按钮时,则会显示让用户输入具体的通讯录的页面,如下边左边第一张图所示

  而在通讯录列表中,用户可以点选某一个已存在的联系人的信息进行查看,查看的实际效果图如上图的第二张图所示,这里用户可以对信息进行编辑修改,再保存,保存后会回到

  通讯录列表的界面。同时,用户如果点“delete”按钮,会显示出如下图的界面,询问用户是否真正要删除该用户的联系信息。

  而在整个应用程序中,由于考虑到要处理的记录数量会大,以及移动设备的处理能力,一个友好的做法是在处理数据时,添加一个表示当前进度的进度的图标,如下图:

  总结一下,整个应用的实际流程如下图所示:

  jQuery Mobile 页面设计

   现在我们来看下如何使用jQuery Mobile框架去设计页面元素。在jQuery Mobile框架设计的HTML页中,通常是一个页面中有一个页面容器,而页面容器中则存在多个页面。页面容器以date-role=“page”作标 识,而普通页面以date-role=“content”作标识。在一个页面中,页面头部和尾部是可选的部分。在我们的这个应用中,有两个页面是都有头部 和尾部的,一个页面没有头部和尾部,下面看示例代码:

<div data-role="page">
  <div data-role="header">...</div>   <div id="contentWithHeaderAndFooter1" data-role="content">...</div>   <div data-role="footer">...</div>
  <div data-role="header">...</div>   <div id="contentWithHeaderAndFooter2" data-role="content">...</div>   <div data-role="footer">...</div>
  <div id="contentWithNoHeaderAndFooter" data-role="content">...</div></div>

  在上面的代码中,展示了如何在一个容器页面中包含了三个页面,其中有2个页面是有页头和页脚的,分别用data-role="header"和data-role="footer"标识。

   在本应用中,创建帐号、通讯录列表和进度图标都是以内容页的形式出现,而在ListPage.html中将会有一个页面容器包裹着它们,而 DetailPage.html中也有一个页面容器,其中包含三个页面,分别是“空的通讯录”,“已经存在的通讯录”和“提示是否删除通讯录”,下图表示 了它们之间的结构关系:

  如何整合前端代码和Android后端JAVA代码

   在本篇教程中,我们将重点学习如何在jQuery Mobile设计的前端页面HTML/JAVASCRPT中,去访问Android中后端的Java应用程序,以及它们之间如何互相交互。要知 道,jQuery Mobile只是帮助开发者用自己熟悉的HTML/Javascript等知识去开发出统一界面,能在不同平台上运行的应用,但它并没有跟Android 整合的机制,因此我们分三个部分去讲解如何:

  1. 通过Javascript去访问Android的Java代码

  2. Android Java应用访问前端Javascript/HTML代码

  3. 在前后端交互中参数的类型问题

  通过Javascript去访问Android的Java代码

  首先来学习如何通过Javascript去访问Android的Java代码。Android提供了一个方法,可以供Javascript 去访问Java应用,这个方法是位于android.webkit.WebView类中的

  addJavascriptInterface(Object object, String interfaceName) 方法。这个方法允许从Javascript代码去访问在WebView中运行的Java类中的public方法。要注意的是,WebView其实也是 android.view.View中的一种。WebView是Android中显示HTML页面和Javascript的浏览器。其 中,addJavascriptInterface方法中的obj为和javascript通信的应用程序,interfacename为提供给 JAVASCRIPT调用的名称,下面这个图,清楚地显示了两者之间的调用关系:

   下面这段代码,显示了ContactsActivity 这个类的实例,如何通过addJavascriptInterface方法,对外暴露为一个Javascript对象,对外的接口名称为 “contactSupport”。其中ContactsActivity中有很多public方法,它向外暴露了其中的deleteContact() 方法,

import android.webkit.WebView; import android.app.Activity; ... public class ContactsActivity extends Activity {   WebView webView;   ...   public void onCreate(Bundle savedInstanceState) {     ...     webView =new WebView(this);     ...     webView.addJavascriptInterface(this, "contactSupport");     ...   }   public void  deleteContact(String contactId, String displayPage){     ...   }

  下面的Javascript代码则显示了如何访问后端Java代码ContactsActivity 对象实例中的

  deleteContact方法

<script>   ...   function someJavaScriptFunction(){     ..     contactSupport.deleteContact(contactIdVar.val(),'ListPage.html');  }   ... </script>

  Android Java代码如何访问前端Javascript代码

  在本应用中,我们使用WebView类中的loadUrl(String url)方法去实现两个目的:

  (1)在Webview浏览器中加载HTML页 (2) 在WebView中加载HTML时,可以一道加载其中的Javascript。我们要注意如下两点:

  · 在同一个容器页面中,不同内容页之间的跳转,都使用Javascript代码。

   · Transition from one container page to another is performed by Java code usingWebView.loadUrl(String url). The container page to display is passed to Java code from JavaScript as a callback parameter.

  在不同的容器中的互相调用,需要在WebView的Java应用程序中,通过使用

  WebView.loadUrl(String url)去加载,下面这个图讲解了Java后端代码如何访问前端Javascript代码的步骤:

  · 用户首先访问HTML网页,这时调用Javascipt显示页面

  · 接着,Javascript进行一些数据的处理,并调用后端的Java代码。

  · 在Java代码处理完后,会通过loadurl的方法,回调前端的Javascript代码或者加载HTML页。

  下面的代码,讲解了前端的Javascript 代码调用了后段的delteContact()方法后,删除了数据库中的记录,然后会重新加载一个HTML页进行显示。

import android.webkit.WebView; import android.app.Activity; import android.os.Handler; ... public class ContactsActivity extends Activity {   WebView webView;   private Handler handler =null;   ...   public void onCreate(Bundle savedInstanceState) {     ...     webView =new WebView(this);     ...     handler =new Handler();     ...   }
  public void deleteContact(String contactId, String displayPage){     ContactUtility.deleteContact(contactId,...);     loadPage(displayPage);   }  
  public void loadPage(String in){     final String url ="file:///android_asset/www/"+ in;     loadURL(url);   }  
  private void loadURL(final String in){     handler.post(new Runnable() {       public void run() {         webView.loadUrl(in);       }     });   }

   这里,我们用到了Android中的Handler消息处理机制。本文不打算详细讲解Handler机制的用法,详细的请参考Android手册。这里 简单提一下Handler消息处理机制,主要是在Android中,新启动的线程是无法刷新或者访问UI界面的,因此就要使用Handler机制。在这 里,deleteContact()方法是无法直接调用 WebView.loadUrl()的,主要有两个原因,一个是WebView实例是在onCreate方法中创建调用的,这是在主线程中;第二个原因是 当Javascript去调用deleteContact()时,执行它的线程实际上是跟ContactsActivity中的onCreate()方法 中的主线程是不同的。因此,我们不难理解下面的三个步骤:

  在deleteContac()中,我们删除了某条通讯录记录。

  接下来,我们调用loadPage方法,这里我们指定了将要跳转的显示页面,并在前面加了file:// android_asset/www/的前缀,意思是我们跳转的这个页面,实际上是存放在android_asset/www目录下的。

   Finally, we call the loadURL() method to have the Handler object call the WebView.最后,我们在loadURL方法中使用Handler机制的post,在新开的线程中加在WebView的loadUrl方法,并将其发 送到消息队列中去。

  如何调用前端的Javascript

  现在看下如何在后端的Java代码中,调用前端的Javascript,代码如下:

public class ContactsActivity extends Activity {   ...   public void   getAllContacts(String callback, String accountCallback){     final String accountCallbackFunction ="javascript:"+ accountCallback +"()";
    if(accountName ==null){       loadURL(accountCallbackFunction);         return;     }
    final String json = ContactUtility.getAllContactDisplaysJSON(getContentResolver());     final String callbackFunction ="javascript:"+ callback +"('"+ json +"')";
    loadURL(callbackFunction);   }

  在上面的代码中,getAllContacts方法作用是产生JSON格式的通讯录列表,其结果存放在json变量中。然后再把结果回调给前端的javascript方法去处理解析JSON格式。这里

   的callbackFunction = "javascript:" + callback + "('" + json + "')",通过javascript:前端处理的JAVASCRIPT方法名+JSON格式结果集,返回给前端。最后也是通过loadURL方法,则可以 达到调用前端Javascipt处理的效果。下面看前端Javscript代码部分:

<script>   $(document).ready(function () {     ...     contactSupport.getAllContacts('setContactsList','showAccount');  }); </script>

   在上面的代码中,调用了Java后端的getAllContacts方法,而getAllContacts方法获得JSON格式的结果集后,会调用前端 Javascript的setContactsList方法去处理(这个方法具体内容我们稍侯会介绍),而参数中的showAccount,则在后端的 getAllContacts方法中,会判断如果当前通讯录没有任何数据时,则会重新使用前端的showAccount这个Javascript方法去处 理。

  在前后端交互中参数的类型问题

  在这个应用中,我们在前后端的交互中,只是使用了字符串类型。而其 他类型如Integer等都将被转型为字符串。而象复合类型的对象都将以JSON的形式进行传递交互。在Java后端中,我们会使用Jackson JSON处理类库对Java对象及JSON对象进行转换,在Javascript方面,则采用jQuery.parseJSON()方法去解析后端返回的 JSON,在接下来的教程中,将会具体讲解。

  程序入口介绍

  在我们的应用中,ContactsActivity 是程序的主类,代码如下:

].name;       }       handler =new Handler();
           webView.addJavascriptInterface(this, "contactSupport");        
      // 装载index.html页       loadPage("index.html");   }   ... }

  代码中关键点讲解如下:

  · 首先初始化WebView并允许Webview使用Javascript。

  · 由于在前面已经提到,通讯录的使用必须关联帐号,所以这里使用android.accounts.AccountManager类去检查应用中是否已经存在帐号,如果存在的话,将帐号名称赋值给变量accountName。

  · We initialize the handler field.接着使用handler机制,将ContactsActivity的对象实例和前端的Javascript绑定,交互的接口名称为contactSupport。

  index.html页的代码如下,其中,在jQuery的ready方法中,当加载页面完毕后,就开始加载ListPage.html了。

  ListPage.html

  首先讲解的是ListPage.html代码,其中回忆下前文提到的结构图,可以看到这个页面容器包含了三个内容页,分别是创建帐号,通讯录列表和进度等待,代码如下:

<html><head><B><!-- jQuery Mobile Libraries --></B>   <link rel="stylesheet" href="css-js/jquery.mobile-1.0a3.min.css"/>   <script src="css-js/jquery-1.5.min.js"></script>   <script src="css-js/jquery.mobile-1.0a3.min.js"></script></head><body><B><!-- Container Page --></B><div data-role="page" data-theme="c" id="containerPage">   <B><!-- Contact List --></B>   <div data-role="header" id="hdrList" data-nobackbtn="true">     <h1><img align="top"  src="img/contacts.png"> Contacts</h1>     <a id="buttonAddContact" data-icon="plus" class="ui-btn-right"       href="<B>javascript:addContact();</B>return false;" data-role="button" data-inline="true">Add</a>   </div>   <div data-role="content" id="contentList" data-theme="c">     <ul data-role="listview" data-dividertheme="c" id="contactSelections"></ul>   </div>   <div data-role="footer" id="ftrList"></div>
  <B><!--  Progress --></B>   <div data-role="header" id="hdrProgress" data-nobackbtn="true"  data-theme="c">     <h1>Processing...</h1>   </div>   <div data-role="content" id="contentProgress"  data-theme="c">     <div align="CENTER"><h4>Please wait.</h4></div>     <div align="CENTER"><img id="spin" src="img/wait.gif"/></div>   </div>   <div data-role="footer" id="ftrProgress"  data-theme="c"></div>
  <B><!--  Create Account --></B>   <div data-role="header" id="hdrAccount" data-nobackbtn="true"  data-theme="c">     <h1>Create Account</h1>   </div>   <div data-role="content" id="contentAccount"  data-theme="c">     <div align="CENTER"><img src="img/contacts-master-bgd.png"></div>     <div align="CENTER"><h4>Please enter name of the new account for this application</h4></div>     <div align="CENTER">Contacts created with this application will be associated with the new account specified below.     Other contacts can be viewed, however, cannot be deleted or modified with this application.</div>     <div align="CENTER" id="accountDiv" data-role="fieldcontain">       <input id="accountName" type="text"/>     </div>     <div align="CENTER">       <a href="javascript:createAccount();return false;"<B>data-role="button"         data-inline="true"</B>>Save</a>     </div>     ...   </div>   <div data-role="footer" id="ftrAccount"  data-theme="c"></div>
</div><B><!-- Container Page Ends Here --></B> ...

  以上的代码中,注意如下几点

  · 所有的三个内容页都有页头,页脚和内容区域。其中,每个部分都是用DIV层的方式去定义的,并且定义了data-theme=“c”,这个是使用了jQuery Mobile框架中预先定义好的颜色样式,详细的请参考jQuery Mobile手册中的论述。

  · jQuery Mobile有预先定义好的返回按钮,但我们将在应用程序中去定义,因此这里并不需要,所以设置data-nobackbtn=“true”。

   · 在“Contact List”的内容页中,有一个增加的按钮,它是调用了addContact()方法,这个方法稍后会学习到。而id="contentList"的那个 DIV中,实际上目前的内容是空的,在程序中,会动态把结果集填充到这里,另外请注意这里使用了jQuery Mobile中的listview样式,表明这是一个列表的样式。

  · 注意在“Create Account”中的按钮,其中用了data-incline=“true”,这表示按钮的大小刚好是跟文字“Save”的大小相匹配的。

   下面我们继续分析ListPage.html。接下来,我们看下如何实现同一个时间之显示页面容器中的某个页面,比如我们在新建帐号时,只希望显示新建 帐号的这个div。方法很简单,在jQuery的ready()方法中,将初始化一些变量,以保存页面容器中的页面,这通过jQuery中 的$('#...')选择器就可以实现了。然后,在需要显示某个层的地方,定义hidePage()和showPage()方法,在这些方法中分别调用层 的hide和show方法,就可以实现了。下面是例子,部分雷同的代码省略,详细见代码下载:

<script>   var hdrListVar;   var contentListVar;   var ftrListVar;   var hdrProgressVar;   var contentProgressVar;   var ftrProgressVar;   var hdrAccountVar;   var contentAccountVar;   var ftrAccountVar;
  $(document).ready(function () {     // Initialize commonly used variables     hdrListVar = $('#hdrList');    contentListVar = $('#contentList');    ftrListVar = $('#ftrList');    hdrProgressVar = $('#hdrProgress');    contentProgressVar = $('#contentProgress');    ftrProgressVar = $('#ftrProgress');    hdrAccountVar = $('#hdrAccount');    contentAccountVar = $('#contentAccount');    ftrAccountVar = $('#ftrAccount');    ...   });
  ...   function hideList(){     hdrListVar.hide();     contentListVar.hide();     ftrListVar.hide();   }
  function showList(){     hideProgress();     hideAccount();     hdrListVar.show();     contentListVar.show();     ftrListVar.show();   }
  function hideProgress(){     hdrProgressVar.hide();     contentProgressVar.hide();     ftrProgressVar.hide();   }
  ... </script>

  接下来,我们看下getAllContacts()方法,这个方法中,是获得通讯录列表,代码如下:

public void getAllContacts(String callback, String accountCallback){   final String accountCallbackFunction ="javascript:"+ accountCallback +"()";
  if(accountName ==null){     loadURL(accountCallbackFunction);     return;   }   final String json = ContactUtility.getAllContactDisplaysJSON(getContentResolver());   final String callbackFunction ="javascript:"+ callback +"('"+ json +"')";   loadURL(callbackFunction); }

   We had partially reviewed that code before. To recap:这段代码之前已经提到,其中我们着重看getAllContactDisplaysJSON方法,它会把后端的结果集取出,转变为JSON格 式的字符串,然后回调到前端的Javascript中的方法去把JSON格式的数据重新整理。在我们的应用中,是按字母表顺序把联系人的姓名进行分组,下 面我们来看其JSON格式的数据集,关于JSON本文不再详细展开论述,请参考相关文档。

","displayName":"Bohme Jacob","key":"B"}     ]   },   ...   ] }

  可以看到,其中按字母表顺序进行了分组,key属性代表的是字母,values的值是一个JSON格式的数组,包含的是每个字母下的联系人的具体通讯录。

  接下来,我们看下前端页面的Javascript如何解析后端传送过来的JSON格式的字符串。代码如下:

; j < tmpValues.length; j++){             var tmpDisplayName = tmpValues[j].displayName;             var tmpContactId = tmpValues[j].contactId;             var tmpLiFragment ='<li><a href="javascript:showContact(' +              tmpContactId +');return false;">'+tmpDisplayName+'</a></li>';            contactSelectionsVar.append(tmpLiFragment);           }         }       }     }     contactSelectionsVar.listview('refresh');    showList();   }   ... </script>

  · 首先,利用了jQuery的parseJSON方法,去解析后端获得的JSON格式代码,解析后的赋值给tmpJson变量。

  然后,使用var tmpContacts = tmpJson.contacts;一句,获得了前文提到的JSON格式中的CONTACTS部分的内容,然后再使用一个FOR循环,在循环体内,每次通过

  var tmpKey = (tmpContacts[i]).key,获得的JSON字符串中的key部分(即每个字母),

  · 然后将tmpKey变量与'

  组合成变量tmpKeyFragment。其中

  是jQuery Mobile中的列表项目分割符号。

  · .再将tmpKeyFragment变量,使用jQuery的append方法添加到contactSelectionsVar这个DIV区域中。

  · 接下来的这步,是先读取JSON字符串中的values属性中的值,变量tmpValues存放的就是每个字母下的所有通讯录联系人列表,然后使用循环去读取每个联系人的contactId和displayName。

   再把tmpDisplayName和 tmpContactId组合成tmpLiFragment变量,注意这里加入了一个链接',其目的是当用户点这个联系人的名称时,会用 javascript调出另外的显示详细信息的页面。同样,最后我们将其添加到contactSelectionsVar这个div层中。

  · 最后,我们使用contactSelectionsVar.listview的refresh方法,更新列表。

  下图是该部分代码跟实际效果的对应图,可以清楚看到两者间的结构:

  小结

   在本系列教程的第一篇,我们介绍了将要设计的应用的概况,页面结构和jQuery Mobile框架中页面的一些元素知识,也介绍了Android中的后端JAVA程序如何跟前端的Javascript进行互相数据交互的基本知识。在下 篇教程中,我们将学习如何新建立一个通讯录的帐号,以及如何对通讯录列表进行增删改。

使用Jquery Mobile设计Android通讯录的更多相关文章

  1. Jquery Mobile设计Android通讯录第二章

    本文是jQuery Mobile设计Android通讯录系统教程的第二篇,在上一篇教程中(http://publish.itpub.net/a2011/0517/1191/000001191561.s ...

  2. 使用jQuery Mobile实现新闻浏览器(3)

    在本教程的前两篇文章中,笔者分别向大家介绍了使用jQuery Mobile框架如何去设计手机新闻浏览器,其中实现了一个WEB版本的新闻浏览器,在本教程的最后一篇中,将讲解如何将已实现的web版本的新闻 ...

  3. 分享15款为jQuery Mobile定制的插件

    jQuery Mobile 1.0 已经发布了, 做为jQuery的移动设备类库, 并且依靠着jQuery这个及其受欢迎的类库,必将带给大家不一样的使用体验,基于jQuery Mobile的插件开发必 ...

  4. Android+Jquery Mobile学习系列(6)-个人信息设置

    本节开始,进行代码的实战练习.我的这个App是管理保险客户信息的,数据采用Sqlite存储在本地手机上,第一次使用需要先登记自己的个人信息,这个功能非常简单,也无关紧要,我是拿这个练手,方便做后面复杂 ...

  5. PhoneGap与Jquery Mobile组合开发android应用的配置

    PhoneGap与Jquery Mobile结合开发android应用的配置 由于工作需要,用到phonegap与jquery moblie搭配,开发android应用程序. 这些技术自己之前也都没接 ...

  6. 使用jQuery Mobile + PhoneGap 开发Android应用程序(转)

    使用jQuery Mobile + PhoneGap 开发Android应用程序(转) 一.简介 jQuery Mobile是jQuery在手机上和平板设备上的版本.jQuery Mobile 不仅给 ...

  7. PhoneGap与Jquery Mobile结合开发android应用配置

    由于工作需要,用到phonegap与jquery moblie搭配,开发android应用程序. 这些技术自己之前也都没接触过,可以说是压根没听说过,真是感慨,在开发领域,技术日新月异,知识真是永远学 ...

  8. 使用jQuery Mobile和Phone Gap开发Android应用程序

    经过了一段时间的学习,初步了解了该如何使用jQuery Mobile和 Phone Gap来开发一个Android应用程序,也想把这些东西介绍给大家. 1. 软件准备 要进行android app的开 ...

  9. Android+Jquery Mobile学习系列(4)-页面跳转及参数传递

    关于页面转场,这个必须得专门列出来说明一下,因为Jquery Mobile与普通的Web发开有一些区别,这个对于新手如果不了解的话,就会钻到死胡同.撸主前段时间就是很急躁地上手开发程序,结果在页面转场 ...

随机推荐

  1. 李洪强iOS开发之苹果使用预览截图

    李洪强iOS开发之苹果使用预览截图 01 在预览的图片中选中你要截得区域  02 - command + C   03 - Command + N 04 - Command + S (保存)

  2. hdu 4472 Count

    递推,一般的dp值: #include<stdio.h> #include<string.h> #define mod 1000000007 ]; int Dp() { a[] ...

  3. linux下使用crontab定时备份MYSQL数据库的方法:

    摘要 linux下使用crontab定时备份MYSQL数据库的方法: 只需按照下面3步做,一切都在你的掌控之下: 第一步:在服务器上配置备份目录代码: ------------------------ ...

  4. 谈谈MVC模式

    谈谈MVC模式   作者: 阮一峰 1. 如何设计一个程序的结构,这是一门专门的学问,叫做"架构模式"(architectural pattern),属于编程的方法论. MVC模式 ...

  5. Win8.1安装VirtualSVN Server发生service visualSVN Server failed to start解决办法

    Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for mo ...

  6. Spring中 @Autowired注解与@Resource注解的区别

    Spring中 @Autowired注解与@Resource注解的区别在Spring 3.X中经常使用到@Autowired和@Resource进行装配.这两个注解的差异在何处???相同点:@Reso ...

  7. HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)

    Seam Carving DescriptionFish likes to take photo with his friends. Several days ago, he found that s ...

  8. 禁用和启用链接(a元素|LinkButton)的js方法

    4 function disableLink(link) {5     //设置href属性6     link.href = "javascript:void(0);";7    ...

  9. javascript 简繁转换

    js 简繁转换 function copy(ob) { var obj=findObj(ob); if (obj) { obj.select();js=obj.createTextRange();js ...

  10. 完全自制的五子棋人机对战游戏(VC++实现)

    五子棋工作文档 1说明: 这个程序在创建初期的时候是有一个写的比较乱的文档的,但是很可惜回学校的时候没有带回来……所以现在赶紧整理一下,不然再过一段时间就忘干净了. 最初这个程序是受老同学所托做的,一 ...