城市成语接龙

来源:互联网 发布:淘宝花店 编辑:程序博客网 时间:2024/04/28 07:22
1、目的:城市成语接龙
2、步骤:
  1)爬取城市名的数据。
  2)删除省市一类的后缀,删除民族名,去掉一个字的城市,事实上还有很多不准确,例如:清新*区和滨海*新区,新字很不好处理。
  3)获取城市名的拼音。这步多音字处理不好。使用了插件,不过目前没有太好的插件
  4)接龙最多100次

3、本来是为了小库公司的面试准备的,结果呵呵呵。

package www.xyb.com;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.URL;import java.net.URLConnection;import java.util.Iterator;import java.util.Map;import java.util.Scanner;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;import java.util.regex.Matcher;import java.util.regex.Pattern;//汉字转拼音,插件import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;public class idiom {/*** * 存储所有从网页上爬到的地名,使用set为了直接去除重复(存在市辖区一类的重复) */public Set<String> treeSet = new TreeSet<String>();/*** * 存储处理过的地名 */public Map<String, TreeSet<String>> Toponym = new TreeMap<String, TreeSet<String>>();/*** * 用来存储行政区域名,要在地名中删除掉 */public String area[] = { "省", "自治区", "市", "特别行政区", "地区", "盟", "自治州", "自治县", "县", "联合旗", "自治旗", "旗", "特区", "新区","区" }; // 新区并不是真正的行政区域/*** * 用来存储民族,要在地名中删除掉 */public String nation[] = { "蒙古族", "回族", "藏族", "维吾尔族", "苗族", "彝族", "壮族", "布依族", "朝鲜族", "满族", "侗族", "瑶族", "白族", "土家族","哈尼族", "哈萨克族", "傣族", "黎族", "傈僳族", "佤族", "畲族", "高山族", "拉祜族", "水族", "东乡族", "纳西族", "景颇族", "柯尔克孜族", "土族","达斡尔族", "仫佬族", "羌族", "布朗族", "撒拉族", "毛南族", "仡佬族", "锡伯族", "阿昌族", "普米族", "塔吉克族", "怒族", "乌孜别克族", "俄罗斯族", "鄂温克族","德昂族", "保安族", "裕固族", "京族", "塔塔尔族", "独龙族", "鄂伦春族", "赫哲族", "门巴族", "珞巴族", "基诺族", // 之后的都不是正式的民族名"各族", "蒙古", "塔吉克", "哈萨克", "维吾尔" };/*** * 获取网页内容 *  * @param url *            网址 * @return 网页源码 */public String SendGet(String url) {// 定义一个字符串用来存储网页内容String result = "";// 定义一个缓冲字符输入流BufferedReader in = null;try {// 将string转成url对象URL realUrl = new URL(url);// 初始化一个链接到那个url的连接URLConnection connection = realUrl.openConnection();// 开始实际的连接connection.connect();// 初始化 BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));// 用来临时存储抓取到的每一行的数据String line = "";while ((line = in.readLine()) != null) {// 遍历抓取到的每一行并将其存储到result里面result += line;}} catch (Exception e) {System.out.println("发送GET请求出现异常!" + e);e.printStackTrace();}// 使用finally来关闭输入流finally {try {if (in != null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}return result;}/*** * 使用字符串截取的方法获取所有地名。 * 本打算用正则表达式,当时不太会用。正则表达式方法参考 * http://blog.csdn.net/fengjiexyb/article/details/77415885 * @param targetStr 网页源码 */public void getToponym(String targetStr) {while (targetStr.indexOf("</span></b></p></div>") != 0) {targetStr = targetStr.substring(targetStr.indexOf("<span style=\"font-family: 宋体\">") + 30);String toDel = "<";int index = targetStr.indexOf(toDel);String str = targetStr.substring(0, index).replace(((char) 12288) + "", "");// 全角空格為12288if (str != "" && str != null && str.length() != 0) {// 不要空格串treeSet.add(str);}targetStr = targetStr.substring(targetStr.indexOf(str) + 7).trim();}}/** * 处理地名。删除掉 省、市、自治区等字样,去除民族字样, 去除一个字的地名,总计2900+ *  * (一级行政区)省级行政区共34个其中:23个省、5个自治区、4个直辖市、2个特别行政区; * (二级行政区)地级行政区共334个其中:8个地区、3个盟、30个自治州、293个市; * (三级行政区)县级行政区共2851个其中:1444个县、117个自治县、49个旗(含一个联合旗)、3个自治旗、 * 367个县级市、869个(市辖)区、1个林区(神农架,其他的都是市辖区)、1个特区; *  */public void processToponym() {for (String value : treeSet) {//去除省市字样for (String s : area) {value = delString(value, s);}//去除民族for (int i = 0; i < 3; i++) {//最多存在3个民族字样for (String s : nation) {value = delString(value, s);}}// 处理异常情况,删除大部分一个字的名字if (value.length() > 1 && !value.equals("市辖") && !value.equals("神农架林") && !value.equals("省直辖县级行政区划")&& !value.equals("自治区直辖县级行政区划")) {addToponym(value);}}//添加部分异常处理的地名addToponym("清新");// 清新区addToponym("神农架");}/*** * 将地名和首字母的拼音存在map中。 * 每个拼音对应一个set,存储多个首字拼音相同的地名。便于查找 * @param value 地名汉字 */private void addToponym(String value) {//获取地名拼音,多音字存在多条记录String[] pinyins = getPinyin(value);//多音字的地名存储多份for (String pinyin : pinyins) {// 使用set为了直接去除重复TreeSet<String> al = new TreeSet<String>();//转换拼音插件存在第5声调,不知道为啥if (pinyin.contains("5"))return;if (Toponym.get(pinyin) == null) {al.add(value);} else {al = Toponym.get(pinyin);Toponym.remove(pinyin);al.add(value);}Toponym.put(pinyin, al);}}/*** * 获取首字拼音,多音字用,分隔 *  * @param value 地名汉字 * @return首字母的所有拼音 */private String[] getPinyin(String value) {HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//拼音模式,有声调,用数字表示format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);//u:用v表示format.setVCharType(HanyuPinyinVCharType.WITH_V);String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(value.charAt(0), format);return pinyinArray;}/*** * 去除末尾的字符串 *  * @param value 地名 * @param s 去除的字符串 一般是省市、民族 * @return 去除后的字符串 */private String delString(String value, String s) {Pattern pattern = Pattern.compile("(.*)" + s + "$");Matcher matcher = pattern.matcher(value);if (matcher.find()) {value = matcher.group(1);}return value;}/*** * 获取下一个接龙的城市名 * @param city 前一个城市 * @return 下一个城市名 */private String getNextCity(String city) {// 获取最后一个字的拼音String[] pinyins = getPinyin(city.substring(city.length() - 1, city.length()));//所有待选的地名TreeSet<String> citys = new TreeSet<String>();//在所有的拼音中选择for (String pinyin : pinyins) {if (!pinyin.contains("5")) {TreeSet<String> ts = Toponym.get(pinyin);if (ts != null) {for (String s : ts) {citys.add(s);}}}}//没有可以接龙的城市if (citys.size() == 0)return null;// 获取随机数int ranInt = (int) (Math.random() * citys.size());Iterator<String> it = citys.iterator();int i = 0;while (it.hasNext()) {if (i == ranInt)return it.next().toString();elseit.next();i++;}return null;}public static void main(String[] args) {idiom id = new idiom();// 定义即将访问的链接String url = "http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html";// 访问链接并获取页面内容String result = id.SendGet(url);// 获取地名id.getToponym(result);// 处理地名id.processToponym();System.out.println("请输入初始的城市名:");//获取输入城市Scanner reader = new Scanner(System.in);String firstCity = reader.nextLine();//获取下一个城市String nextCity = id.getNextCity(firstCity);int i = 0;//最多接龙100次while (nextCity != null && i < 100) {i++;System.out.println(nextCity);nextCity = id.getNextCity(nextCity);}if (i >= 99) {System.out.println("程序执行了100次,已停止。");} else {System.out.println("程序执行了" + i + "次,无法继续进行,已停止。");}reader.close();}}