个人练习程序

此文于2024年8月17日更新。
我不想和任何人说话,大家不要打扰我。
此页面程序自动排版有问题,一些程序被移到程序框外面了。下面一些内容会白屏几秒钟,可能因为程序框内容量太大。
unity游戏源码和教程:智能分析话语的三维唯美世界。
这个游戏的源码(含教程文档)我放到了夸克网盘https://pan.quark.cn/s/618fb9459029

小区:

小区傍晚的雪:

小区的晚上:

家里:

市中心:

市街道:

郊区:

(一)声明
小区场景的三维模型来自于UnityStore的unity包:Low Poly Japanese Housing Complex。很多人在用,所以我的游戏和其他人的游戏出现这个相同场景,不是抄袭。而且那只是个三维模型,程序要自己写,每个人写的程序是不同的。
市中心、市街道、郊区场景,来自UnityStore的unity包:258316_Anime_Tokyo_(Japanese_City),也有很多游戏开发者在用这个场景三维模型。
人物三维模型来自于网络上大家常见、常用的三维人物模型,我做了骨骼绑定、蒙皮、走路动画。
雪景程序来自于unity包:Global Snow,天空盒来自于unity包:AllSky。

(二)基本操作
W键(长按):向前走。
S键(长按):向后走。
A键(长按):向左转。
D键(长按):向右转。

鼠标左右上下移动来控制摄像机视角(屏幕视角),人物前进方向自动朝向摄像机视角。
键盘右边的方向键:上:抬高摄像机视角,下:降低摄像机视角,左:拉近摄像机视角,右:拉远摄像机视角。
F键(单击):第三人称视角和第一人称视角的切换。第三人称视角适合用在街上,第一人称视角适合用在家里。

空格键(单击):显示或关闭文字的输入输出框(默认不显示,需要点击空格键才显示)。输入完文字后,按回车键发送。
M键(单击):背景音乐,继续按,是下一首背景音乐。

数字键1(单击):小区场景(默认场景)。
数字键2(单击):市中心场景。
数字键3(单击):市街道场景。
数字键4(单击):郊区场景。
Esc键(单击):退出游戏。

小区场景中:
H键(单击):小区场景时,可以一键回家。
G键(单击),男主角和女主角分开,女主角停留在原地。男主角走远后,第二次按G键,女主角会自动寻路来找男主角,到男主角身边。
J键(单击):女主角一键换服装。
K键(单击):每点击一次,就变换一次天色。浅夜→夜晚→白天→傍晚→夜晚→清晨→白天→阴天。
L键(单击):正常景色和雪景的切换。

(三)
即便没有安装unity编辑器的情况下,play文件夹里DreamStart.exe可以直接运行此游戏。

unity的一份源码,只能适配一个编辑器版本,这个源码适配的是2022.3.38,其它版本打开此源码,会故障。
unity导入此项目时,不是导入哪个具体启动文件,而是用unity Hub(unity启动器)直接打开(导入)DreamStart文件夹。
如果unity编辑器没有显示场景,就在编辑器里手动打开park文件夹里的Scenes文件夹里的park场景文件即可。
在unity编辑器界面,不要把窗口最大化后再运行游戏,那样运行不了。但可以在游戏后,再最大化窗口。
地上的蓝色,是自动寻路烘培的地面,游戏运行时不显示那蓝色。

(四)话语分析
话语分析是有用的,假如游戏中,你是队长,带着NPC队友张三和李四,路上遇到蛇,你可以说“张三打蛇,李四保护张三。”这就需要先分析出主语、谓语、宾语,程序才能处理。
输入完成后,按回车键发送。

示例:
输入:猫吃鼠
显示:主语:猫,谓语动词:吃,宾语:鼠

输入:白色的猫吃黑色的鼠
显示:主语:猫,谓语动词:吃,宾语:鼠,主语的形容词:白色的,宾语的形容词:黑色的

输入:两只猫吃3只鼠
显示:主语:猫,谓语动词:吃,宾语:鼠,主语的数词:2只,宾语的数词:3只

输入:张三的猫吃李四的鼠
显示:主语:猫,谓语动词:吃,宾语:鼠,主语的名词所有格:张三,宾语的名词所有格:李四

输入:张三给李四苹果
显示:主语:张三,谓语动词:给,间接宾语:李四,直接宾语:苹果

输入:张三让李四打扫教室
显示:主语:张三,谓语动词:让,宾语:李四,宾语补足语动词:打扫,宾语补足语名词:教室

输入:2024年张三在学校吃饭
显示:主语:张三,谓语动词:吃饭,时间:2024年,地点:学校

如果分析显示不了,可能词语不在词库里。先找动词分割句子,再找名词,所以如果动词不在词库里,即便名词在词库里,也没用。
连接的单机数据库是garden.db,是sqlite单机数据库,就是在用户电脑的游戏文件里的,不联网的、不用安装服务的、不用配置的,直接就可以用的数据库。

(五)
人工智能分析话语的源码教程:
这仅是前六章,以后我还会继续写。用C#语言写的。如果找不出主语、谓语、宾语等,因为词语不在词库中,那就需要手动添加进词库。还有,先按动词分割句子,如果动词找不到,后面名词就算在词库,也找不到。目前词库里,名词7128个,动词5886个,形容词1777个。
每一章是在前一章的基础上增加内容,从而使读者能循序渐进的看懂。如果直接给个结果,读者不知道怎么一步步变化来的,那也就看不懂结果了。

前三章概述:
第一章的主要内容
判断输入的句子中,是否包含名词。
找出句子的主语、谓语、宾语。
解决三个基本问题
前面的方法,靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
对于第一个问题的解决方法:
新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
所以创建一个函数:WordCover(覆盖)。
词语槽(WordBox)存放这些找到词,以实现覆盖和吸收。

第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
对于第二个问题的解决方法:
找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
所以创建一个de函数。

第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
对于第三个问题的解决方法:
建立词性辨析表:verb_judge,词性辨析表在数据库里,已经做好了。

第二章的主要内容
基本单句有六种句型:
只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
主语(动作执行者)-谓语(动作):张三摔倒。
主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
前面只说了主谓宾句型,还要处理其它句型。

双宾语句型:
双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

宾语补足语句型:
和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

第三章的主要内容
省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。

名词合并:
名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
合并方法:如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。

动词合并:
例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词。

动词前面是否有否定词,也很重要。
例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。

第五章:
对于数词,之前用正则表达式直接抽取出数字,那种方法太简单了,我用逐字分析的方法重写了。
还有就是分析出时间,不仅分析出是年、月、日、时、分,还要分析出一些时间词:
"今天", "明天", "后天", "昨天", "前天", "这个月", "下个月", "上个月", "今年", "明年", "去年"
"早晨", "上午", "中午", "下午", "傍晚", "晚上", "傍晚", "夜晚", "半夜", "黎明", "黄昏", "清晨"
"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日", "礼拜一", "礼拜二", "礼拜三", "礼拜四", "礼拜五", "礼拜六", "礼拜天"
"春天", "夏天", "秋天", "冬天", "春季", "夏季", "秋季", "冬季"
"元旦", "大年三十", "除夕", "春节", "大年初一", "大年初二", "大年初三", "正月十五", "寒假", "清明节", "五一节", "劳动节", "儿童节", "暑假", "中秋节", "国庆节", "圣诞节", "假期", "休息日"

第五章可用的动词单位是:
"个", "名", "位", "只", "头", "匹", "条", "棵", "朵", "片", "根", "座", "栋", "台", "部", "本", "块", "件", "盏", "把", "所", "辆", "艘", "架", "扇"

"米", "厘米", "毫米", "分米", "公里", "里", "微米", "纳米", "克", "斤", "公斤", "吨", "毫克", "升"

先找到动词单位,才能找到数词。

第六章:
直接宾语的定语(形容词、数词、名词所有格),在间接宾语和直接宾语之间。
例如张三给李四红色的苹果,李四是间接宾语,苹果是直接宾语,红色的是形容词。

间接宾语的定语在谓语动词和间接宾语之间,对于谓语动词右边句,也就是句子开始到间接宾语之间。
例如张三给美丽的李四苹果,李四是间接宾语,美丽的是形容词。

宾语补足语名词的定语(形容词、数词、名词所有格)在宾语补足语动词的右边。
例如张三让李四打扫蓝色的房子,打扫是宾语补足语的动词,房间是宾语补足语的名词,蓝色的是形容词。

第六章增加了猜测词语的功能,但不建议用猜测词语,因为如果一个词语,词库里没有,要靠程序猜测,那么游戏剧情肯定对这个词语没做任何准备,就算猜测出这个词,也没用。
例如张三爱雅娜,名词词库肯定没有“雅娜”这个词,但是谓语动词“爱”字右边的句子的两个字,显然是宾语名词,所以猜测词语是很容易猜测的。
就算猜测出宾语是雅娜,又怎样了呢,对雅娜的信息和属性,什么都没有设置,程序没法分析。甚至连雅娜到底是一个人还是一块石头,都没法分析。
那么张三带着雅娜去海边,到底是张三带着女人雅娜去海边,还是张三带着石头雅娜去海边,准备扔石头玩水漂。计算机分析程序一头雾水,所以猜测词语会降低计算机的分析能力。
还是勤快点吧,把词语录入词库,并给词语设置信息和属性。什么时候用猜测词语呢?词库词汇量还不够多的时候,只能靠猜词来补偿,但这不是长远的办法。
这就好比编程强调“对变量,要先定义,后使用”,猜测词语就好比不定义就直接使用。

猜测词语的原理:抽取掉已知的词语(词库里有的词语),剩下的未知的词语(词库里没有的词语),就是要猜测的词。
例如“张三喜欢美丽的雅娜”,谓语动词右边句是“美丽的雅娜”,词库已有的形容词是“美丽的”,抽取掉形容词“美丽的”,剩下的词语“雅娜”就是要猜测的宾语。

第一章
人工智能处理语言的意义
假如你是队长,带着两个NPC队友张三和李四,路上遇到一条蛇。你下令张三打蛇,李四保护张三,这就需要先分析出句子的主语、谓语、宾语,程序才能操作命令。

单机数据库的意义
这个程序用的是单机数据库sqlite,单机游戏一般都用单机数据库sqlite。因为一方面,单机数据库不联网,在用户电脑的游戏文件里,而不是在服务器上。另一方面,单机数据库不用安装服务,不用做配置,用户啥都不用管,直接就能用。

需要的插件说明
有词库的sqlite数据库garden.db。其中名词表noun,名词列word_col。动词表verb,动词列word_col。还有词性辨析表verb_judge。
把garden.db放到Assets文件夹的上一级文件夹,也就是程序源码的根目录,就可以在编辑器环境下运行了。生成游戏后,garden.db还要复制到生成游戏的文件夹里。
将C盘→Program Files→Unity→Hub→Editor→2022.3.38→Editor→Data→MoonBleedingEdge→lib→mono→net_4_x-win32文件夹里的Mono.data.sqlite.dll和system.data.dll放到Plugins文件夹里(在Assets文件夹里,自己创建一个Plugins文件夹,字母P大写,系统自动认为那是个存放插件的文件夹)。
在sqlite官网下载sqlite3.dll也放到Plugins文件夹里。
Mono.data.sqlite.dll、system.data.dl、sqlite3.dll是sqlite数据库运行所需的三个插件。

判断输入的句子中,是否包含名词
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mono.Data.Sqlite;

public class sqlitecon : MonoBehaviour
{
public TMP_Text tmpText;//输出框对象
string ShowText;//输出框的内容
string[] noun = new string[7128];//名词数组,名词数量7128
string[] verb = new string[5886];//动词数组,动词数量5886
int i = 0;//数组用的循环变量
public TMP_InputField inputField;//输入框对象

// Start is called before the first frame update
void Start()
{
    //inputField = GetComponent<TMP_InputField>();//输入框获取组件
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    UnityEngine.Debug.Log(i);//显示动词数量
}

// Update is called once per frame
void Update()
{

}

void OnInputEndEdit(string value)
{
    string shuru = inputField.text;//输入框的值
    string jieguo = "不包含";//默认值是不包含
    int m = noun.Length;//名词数组的长度,也就是有多少个名词
    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (shuru.Contains(noun[n]))//包含
        {
            jieguo = "包含";
        }
    }

    tmpText.text = jieguo;//显示结果

}
}

OnInputEndEdit函数里,稍微改变一下,也可以用于找动词。

找出句子的主语、谓语、宾语
例如输入:白色的猫吃黑色的鼠。主语显示:猫,谓语动词显示:吃,宾语显示:鼠。
基本原理:对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mono.Data.Sqlite;

public class sqlitecon : MonoBehaviour
{
public TMP_Text tmpText;//输出框对象
string ShowText;//输出框的内容
string[] noun = new string[7128];//名词数组,名词数量7128
string[] verb = new string[5886];//动词数组,动词数量5886
int i = 0;//数组用的循环变量
public TMP_InputField inputField;//输入框对象
string shuru = "";//输入框的内容

string FindSubject = "";//找到的主语
string FindVerb = "";//找到的谓语动词
string FindObject = "";//找到的宾语

// Start is called before the first frame update
void Start()
{
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量
}

// Update is called once per frame
void Update()
{

}

void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的值

    //找谓语动词
    string jieguo = "不包含";//默认值是不包含
    int m = verb.Length;//动词数组的长度,也就是有多少个动词
    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (shuru.Contains(verb[n]))//包含
        {
            jieguo = "包含";
            FindVerb = verb[n];//找到了动词
        }
    }

    if(jieguo == "包含")
    {
        SplitSentence(FindVerb);
    }


    //tmpText.text = jieguo;//显示结果
}

void SplitSentence(string find_verb)
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "吃";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词的位置(索引)
    int i = 0;//临时变量
    int j = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    UnityEngine.Debug.Log(chang);//显示9

    //计算指定字符在全句中的位置
    index = str.IndexOf(word);//从0计算,例如第2个字符,显示为1,而不是2
    UnityEngine.Debug.Log(index);//显示4

    //截取第3个字符右边的1个字符
    Substring(开始位置,向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符
    UnityEngine.Debug.Log(res);//显示:猫

    //截取指定字符右边的全部字符
    i = index + 1;//指定字符的位置,由于index是从0开始计算的,所以要加1,变为从1开始计算的方式,所以是index+1
    j = chang - (index + 1);//截取长度 = 全句长度 - 指定字符的位置长度
    UnityEngine.Debug.Log(i);//显示5
    UnityEngine.Debug.Log(chang);//显示9
    UnityEngine.Debug.Log(j);//显示4
    res = str.Substring(i,j);
    UnityEngine.Debug.Log(res);//显示:黑色的鼠
    res = str.Substring(index + 1, chang - (index + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:黑色的鼠
    //index变为str.IndexOf(word),chang变为str.Length
    res = str.Substring(str.IndexOf(word) + 1, str.Length - (str.IndexOf(word) + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:黑色的鼠

    //截取指定字符左边的全部字符
    res = str.Substring(0,index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0,str.IndexOf(word));//变化形式
    UnityEngine.Debug.Log(res);//显示:白色的猫

    //截取两个指定字符之间的全部字符
    i = str.IndexOf("猫");
    j = str.IndexOf("鼠");
    res = str.Substring(i+1,j-(i+1));
    UnityEngine.Debug.Log(res);//显示:吃黑色的
    //把i变为str.IndexOf("猫"),j变为str.IndexOf("鼠")
    res = str.Substring(str.IndexOf("猫") + 1, str.IndexOf("鼠") - (str.IndexOf("猫") + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:吃黑色的

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    LeftPart = shuru.Substring(0, shuru.IndexOf(find_verb));
    RightPart = shuru.Substring(shuru.IndexOf(find_verb) + 1, shuru.Length - (shuru.IndexOf(find_verb) + 1));

    /*
    例如句子(shuru)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);
    UnityEngine.Debug.Log(LeftPart);
    UnityEngine.Debug.Log(RightPart);
    */

    if (find_verb != "")
    {
        FindVerb = find_verb;
    }

    if (LeftPart != "")
    {
        FindSubject = SearchNoun(LeftPart);//找名词
    }

    if (RightPart != "")
    {
        FindObject = SearchNoun(RightPart);//找名词
    }

    UnityEngine.Debug.Log(FindSubject);
    UnityEngine.Debug.Log(FindVerb);
    UnityEngine.Debug.Log(FindObject);

}

string SearchNoun(string PartSentence)
{
    //找名词
    string jieguo = "不包含";//默认值是不包含
    string FindNoun = "";//要找的名词
    int m = noun.Length;//名词数组的长度,也就是有多少个名词
    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            FindNoun = noun[n];//找到了名词
        }
    }

    if (jieguo == "包含")
    {
        return FindNoun;
    }
    else
    {
        return "";
    }
}

}

解决三个基本问题
前面的方法,靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
对于第一个问题的解决方法:
新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
所以创建一个函数:WordCover(覆盖)。
词语槽(WordBox)存放这些找到词,以实现覆盖和吸收。

第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
对于第二个问题的解决方法:
找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
所以创建一个de函数。

第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
对于第三个问题的解决方法:
建立词性辨析表:verb_judge,词性辨析表在数据库里,已经做好了。
+--------------+-------------+----------------+
| word_col | type_col | content_col |
+--------------+-------------+----------------+
| 学 | r1 | 生 |
+--------------+-------------+----------------+
| 压 | l1 | 气 |
+--------------+-------------+----------------+

word_col:判断这个字是动词还是名词。
type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
l是字母L的小写,不是数字1。l1是两个不同的字符。
所以创建一个VerbJudge函数。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mono.Data.Sqlite;

public class sqlitecon : MonoBehaviour
{
public TMP_Text tmpText;//输出框对象
string ShowText;//输出框的内容
string[] noun = new string[7128];//名词数组,名词数量7128
string[] verb = new string[5886];//动词数组,动词数量5886
int i = 0;//数组用的循环变量
public TMP_InputField inputField;//输入框对象
string shuru = "";//输入框的内容

string FindSubject = "";//找到的主语
string FindVerb = "";//找到的谓语动词
string FindObject = "";//找到的宾语

string WordBox1 = "";//词语槽1
string WordBox2 = "";//词语槽2
string WordBox3 = "";//词语槽3
string WordBox4 = "";//词语槽4

// Start is called before the first frame update
void Start()
{
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    dbConnection.Close();
}

// Update is called once per frame
void Update()
{

}

void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的值

    //找谓语动词
    string jieguo = "不包含";//默认值是不包含
    int m = verb.Length;//动词数组的长度,也就是有多少个动词
    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (shuru.Contains(verb[n]))//包含
        {
            if (VerbJudge(shuru,verb[n]) == true)
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
            }
            
        }
    }

    if(jieguo == "包含")
    {
        SplitSentence(FindVerb);
    }


    //tmpText.text = jieguo;//显示结果
}

void SplitSentence(string find_verb)
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "吃";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词的位置(索引)
    int i = 0;//临时变量
    int j = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    UnityEngine.Debug.Log(chang);//显示9

    //计算指定字符在全句中的位置
    index = str.IndexOf(word);//从0计算,例如第2个字符,显示为1,而不是2
    UnityEngine.Debug.Log(index);//显示4

    //截取第3个字符右边的1个字符
    Substring(开始位置,向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符
    UnityEngine.Debug.Log(res);//显示:猫

    //截取指定字符右边的全部字符
    i = index + 1;//指定字符的位置,由于index是从0开始计算的,所以要加1,变为从1开始计算的方式,所以是index+1
    j = chang - (index + 1);//截取长度 = 全句长度 - 指定字符的位置长度
    UnityEngine.Debug.Log(i);//显示5
    UnityEngine.Debug.Log(chang);//显示9
    UnityEngine.Debug.Log(j);//显示4
    res = str.Substring(i,j);
    UnityEngine.Debug.Log(res);//显示:黑色的鼠
    res = str.Substring(index + 1, chang - (index + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:黑色的鼠
    //index变为str.IndexOf(word),chang变为str.Length
    res = str.Substring(str.IndexOf(word) + 1, str.Length - (str.IndexOf(word) + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:黑色的鼠

    //截取指定字符左边的全部字符
    res = str.Substring(0,index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0,str.IndexOf(word));//变化形式
    UnityEngine.Debug.Log(res);//显示:白色的猫

    //截取两个指定字符之间的全部字符
    i = str.IndexOf("猫");
    j = str.IndexOf("鼠");
    res = str.Substring(i+1,j-(i+1));
    UnityEngine.Debug.Log(res);//显示:吃黑色的
    //把i变为str.IndexOf("猫"),j变为str.IndexOf("鼠")
    res = str.Substring(str.IndexOf("猫") + 1, str.IndexOf("鼠") - (str.IndexOf("猫") + 1));//变化形式
    UnityEngine.Debug.Log(res);//显示:吃黑色的

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    LeftPart = shuru.Substring(0, shuru.IndexOf(find_verb));
    RightPart = shuru.Substring(shuru.IndexOf(find_verb) + 1, shuru.Length - (shuru.IndexOf(find_verb) + 1));

    /*
    例如句子(shuru)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);
    UnityEngine.Debug.Log(LeftPart);
    UnityEngine.Debug.Log(RightPart);
    */

    if (find_verb != "")
    {
        FindVerb = find_verb;
    }

    if (LeftPart != "")
    {
        FindSubject = SearchNoun(LeftPart);//找名词
    }

    if (RightPart != "")
    {
        FindObject = SearchNoun(RightPart);//找名词
    }

    UnityEngine.Debug.Log("主语:" + FindSubject);
    UnityEngine.Debug.Log("谓语:" + FindVerb);
    UnityEngine.Debug.Log("宾语:" + FindObject);

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(WordBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +--------------+-------------+----------------+
    | word_col | type_col | content_col |
    +--------------+-------------+----------------+
    |   学    |   r1   |    生    |
    +--------------+-------------+----------------+
    |   压    |   l1   |    气    |
    +--------------+-------------+----------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

string SearchNoun(string PartSentence)
{
    //找名词
    string jieguo = "不包含";//默认值是不包含
    string FindNoun = "";//要找的名词
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    WordBox1 = "";
    WordBox2 = "";
    WordBox3 = "";
    WordBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            //FindNoun = noun[n];//找到了名词
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字
            {
                FindNoun = WordCover(noun[n]);
            }
        }
    }

    if (jieguo == "包含")
    {
        return FindNoun;
    }
    else
    {
        return "";
    }
}

string WordCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(WordBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(WordBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (WordBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        WordBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (WordBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(WordBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(WordBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            WordBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (WordBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(WordBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (WordBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        WordBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (WordBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(WordBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(WordBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            WordBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (WordBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(WordBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (WordBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        WordBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (WordBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(WordBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(WordBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            WordBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (WordBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(WordBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (WordBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        WordBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (WordBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(WordBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(WordBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            WordBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (WordBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(WordBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    return WordBox1;//对于主谓宾结构,找主语时,找到的名词只有一个,找宾语时,找到的名词也只有一个,所以只返回WordBox1
}

bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上内容是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }

}

bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +--------------+-------------+----------------+
    | word_col | type_col | content_col |
    +--------------+-------------+----------------+
    |   学    |   r1   |    生    |
    +--------------+-------------+----------------+
    |   压    |   l1   |    气    |
    +--------------+-------------+----------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +--------------+-------------+----------------+
    | word_col | type_col | content_col |
    +--------------+-------------+----------------+
    |   吹    |   l1   |    电    |
    +--------------+-------------+----------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上内容是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

}

第二章
基本单句有六种句型:
只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
主语(动作执行者)-谓语(动作):张三摔倒。
主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
前面只说了主谓宾句型,还要处理其它句型。

双宾语句型:
双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

宾语补足语句型:
和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mono.Data.Sqlite;

public class sqlitecon : MonoBehaviour
{
public TMP_Text tmpText;//输出框对象
string ShowText;//输出框的内容
string[] noun = new string[7128];//名词数组,名词数量7128
string[] verb = new string[5886];//动词数组,动词数量5886
int i = 0;//数组用的循环变量
public TMP_InputField inputField;//输入框对象
string shuru = "";//输入框的内容

string FindSubject = "";//找到的主语
string FindVerb = "";//找到的谓语动词
string FindObject = "";//找到的宾语
string FindBuVerb = "";//宾语补足语的动词
string FindBuNoun = "";//宾语补足语的名词
string FindJianObject = "";//找到的间接宾语
string FindZhiObject = "";//找到的直接宾语

string NounBox1 = "";//名词槽1
string NounBox2 = "";//名词槽2
string NounBox3 = "";//名词槽3
string NounBox4 = "";//名词槽4

string VerbBox1 = "";//动词槽1
string VerbBox2 = "";//动词槽2
string VerbBox3 = "";//动词槽3
string VerbBox4 = "";//动词槽4

string SentenceType = "";//句型

// Start is called before the first frame update
void Start()
{
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    dbConnection.Close();
}

// Update is called once per frame
void Update()
{

}

void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的值

    //找谓语动词
    string jieguo = "不包含";//默认值是不包含动词
    int m = verb.Length;//动词数组的长度,也就是有多少个动词

    VerbBox1 = "";
    VerbBox2 = "";
    VerbBox3 = "";
    VerbBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (shuru.Contains(verb[n]))//包含动词
        {
            if (VerbJudge(shuru,verb[n]) == true)//是动词,不是名词
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
                VerbCover(shuru,verb[n]);//把动词放入动词槽里,看看有几个动词
            }
            
        }
    }

    if(jieguo == "包含")//包含动词
    {
        SentenceType = SentenceJudge();//判断句型(仅从动词情况来判断句型,还不是完全清楚的判断,之后还需进一步判断)
        UnityEngine.Debug.Log("句型:" + SentenceType);
        
        SplitSentence();
    }
    //tmpText.text = jieguo;//显示结果
}

void SplitSentence()
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string word = "嘲笑";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词语的起始位置
    int LastIndex = 0;//指定词语最后一个字符在全句中的位置
    int jie = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    //计算指定字符在全句中的位置
    index = str.IndexOf(word) + 1;//默认从0计算,例如第2个字符,显示为1,而不是2。为了调整为1开始计算,所以加1
    //计算指定词语最后一个字符在全句中的位置
    LastIndex = str.IndexOf(word) + word.Length;

    //截取第3个字符右边的1个字符
    Substring(开始位置, 向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符

    //截取指定字符右边的全部字符
    jie = chang - LastIndex;//截取长度 = 全句长度 - 指定词语最后一个字符的位置长度
    res = str.Substring(LastIndex, jie);
    res = str.Substring(str.IndexOf(word) + word.Length, str.Length - (str.IndexOf(word) + word.Length));//展开形式

    //截取指定字符左边的全部字符
    res = str.Substring(0, index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0, str.IndexOf(word));//变化形式

    //截取两个指定字符之间的全部字符
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    //也可能找到一个动词(主谓宾句型),也可能找到两个动词(宾语补足语句型)
    if (VerbBox1 != "" && VerbBox2 == "")//只找到1个动词,那就是谓语动词
    {
        FindVerb = VerbBox1;
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//找到2个动词
    {
        FindVerb = VerbBox1;//位次在前面的动词是谓语动词
        FindBuVerb = VerbBox2;//位次在后面的动词是宾语补足语动词
    }

    LeftPart = shuru.Substring(0, shuru.IndexOf(FindVerb));
    RightPart = shuru.Substring(shuru.IndexOf(FindVerb) + FindVerb.Length, shuru.Length - (shuru.IndexOf(FindVerb) + FindVerb.Length));

    /*
    例如句子(shuru)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);
    UnityEngine.Debug.Log(LeftPart);
    UnityEngine.Debug.Log(RightPart);
    */

    if (LeftPart != "")
    {
        FindSubject = SearchNoun(LeftPart);//在谓语动词左边句找名词(主语)
    }

    if (SentenceType == "双宾语")//双宾语句型
    {
        FindObject = SearchNoun(RightPart);//找名词

        //谓语动词右边句里,没有第二个宾语名词,那就不是双宾语
        //例如虽然有双宾语句的标志动词“教”字,但他教我数学,是双宾语句,而他教书,是主谓宾句型
        if (NounBox2 == "")
        {
            SentenceType = "主谓宾";
        }
        else
        {
            UnityEngine.Debug.Log("主语:" + FindSubject);
            UnityEngine.Debug.Log("谓语:" + FindVerb);
            UnityEngine.Debug.Log("间接宾语:" + FindJianObject);
            UnityEngine.Debug.Log("直接宾语:" + FindZhiObject);
        }
    }

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        if (RightPart != "")
        {
            FindObject = SearchNoun(RightPart);//在谓语动词右边句找名词(宾语)
        }

        //显示结果
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
    }

    if (SentenceType == "宾语补足语")//宾语补足语句型
    {
        //谓语动词到宾语补足语动词之间的部分里的名词,是宾语名词
        string temp = "";
        //截取谓语动词FindVerb和宾语补足语动词FindBuVerb之间的部分
        temp = shuru.Substring(shuru.IndexOf(FindVerb) + FindVerb.Length, shuru.IndexOf(FindBuVerb) - (shuru.IndexOf(FindVerb) + FindVerb.Length));
        FindObject = SearchNoun(temp);//找名词
        //宾语补足语右边句的名词,是宾语补足语名词,而不是宾语名词
        int WordLastChar = shuru.IndexOf(FindBuVerb) + FindBuVerb.Length;//宾语补足语动词最后一个字符的位置
        if (WordLastChar < shuru.Length)//宾语补足语动词最后一个字符的位置没有到全句末尾,就是说宾语补足语动词后面还有内容,那就是宾语补足语名词
        {
            //截取宾语补足语动词右边的内容
            FindBuNoun = shuru.Substring(shuru.IndexOf(FindBuVerb) + FindBuVerb.Length, shuru.Length - (shuru.IndexOf(FindBuVerb) + FindBuVerb.Length));
        }

        //显示结果
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("宾语补足语动词:" + FindBuVerb);
        UnityEngine.Debug.Log("宾语补足语名词:" + FindBuNoun);
    }

    

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

string SearchNoun(string PartSentence)
{
    //找名词
    string jieguo = "不包含";//默认值是不包含
    string FindNoun = "";//要找的名词
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    NounBox1 = "";
    NounBox2 = "";
    NounBox3 = "";
    NounBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字,才算是名词,否则是名词所有格
            {
                NounCover(noun[n]);
                FindNoun = NounBox1;
            }
        }
    }

    if (jieguo == "包含")
    {
        return FindNoun;
    }
    else
    {
        return "";
    }
}

void NounCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(NounBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (NounBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        NounBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (NounBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(NounBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (NounBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(NounBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (NounBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        NounBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (NounBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(NounBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (NounBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(NounBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (NounBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        NounBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (NounBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(NounBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (NounBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(NounBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (NounBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        NounBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (NounBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(NounBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (NounBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(NounBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    //排序
    if (NounBox1 != "" && NounBox2 != "")//招到了2个名词,放在NounBox1和NounBox2
    {
        string temp = "";//临时变量
        if (shuru.IndexOf(NounBox1) > shuru.IndexOf(NounBox2))//如果NounBox1的名词在句子中的位置大于NounBox2的名词在句子中的位置
        {
            //交换位置,在句子中位置小的名词放前面,从而确保双宾语句型时,NounBox1放的是间接宾语,NounBox2放的是直接宾语,毕竟间接宾语在直接宾语前面
            temp = NounBox1;
            NounBox1 = NounBox2;
            NounBox2 = temp;
        }
        FindJianObject = NounBox1;
        FindZhiObject = NounBox2;
    }

}

void VerbCover(string str,string FindWord)
{
    if (VerbBox1 == "" && FindWord != "")//动词槽还是空的,说明这是找到的第一个词
    {
        VerbBox1 = FindWord;//找到的第1个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽2了
    }
    else if (VerbBox1 != "" && FindWord != "")//动词槽1已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox1))//覆盖:例如找到的词(FindWord)是敲打,动词槽1(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“敲打”覆盖“打”
            FindWord = "";//置空,免得填到动词槽2了
        }
        else if (VerbBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽1(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,不要这个词了,免得填到动词槽2了
        }
    }

    if (VerbBox2 == "" && FindWord != "")//动词槽2是空的,FindWord经过动词槽1,没有覆盖或吸收,说明FindWord和动词槽1的词无关,例如FindWord是喜欢
    {
        VerbBox2 = FindWord;//找到的第2个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽3了
    }
    else if (VerbBox2 != "" && FindWord != "")//动词槽2已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox2))//覆盖:例如找到的词(FindWord)是敲打,动词槽2(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (VerbBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽2(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (VerbBox3 == "" && FindWord != "")//动词槽3是空的,FindWord经过动词槽1和2,没有覆盖或吸收,说明FindWord和动词槽1、2的词无关,例如FindWord是喜欢
    {
        VerbBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (VerbBox3 != "" && FindWord != "")//动词槽3已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox3))//覆盖:例如找到的词(FindWord)是敲打,动词槽3(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (VerbBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽3(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (VerbBox4 == "" && FindWord != "")//动词槽4是空的,FindWord经过动词槽1、2、3,没有覆盖或吸收,说明FindWord和动词槽1、2、3的词无关,例如FindWord是喜欢
    {
        VerbBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (VerbBox4 != "" && FindWord != "")//动词槽4已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox4))//覆盖:例如找到的词(FindWord)是敲打,动词槽4(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (VerbBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽4(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空
        }
    }

    //排序
    if (VerbBox1 != "" && VerbBox2 != "")//招到了个动词,放在VerbBox1和VerbBox2
    {
        string temp;//临时变量
        if (shuru.IndexOf(VerbBox1) > shuru.IndexOf(VerbBox2))//如果VerbBox1的动词在句子中的位置大于VerbBox2的动词在句子中的位置
        {
            //交换位置,在句子中位置小动词的放前面,从而确保VerbBox1放的是谓语动词,而宾语补足语动词放到VerbBox2
            temp = VerbBox1;
            VerbBox1 = VerbBox2;
            VerbBox2 = temp;
        }
    }
    
}

bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上内容是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }

}

bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   吹     |   l1    |      电      |
    +----------+---------+--------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上内容是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

string SentenceJudge()
{
    /*
    判断句型:
    基本单句有六种句型:
    只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
    主语(动作执行者)-谓语(动作):张三摔倒。
    主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
    主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
    双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
    宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
    前面只说了主谓宾句型,还要处理其它句型。

    双宾语句型:
    双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
    但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
    双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
    那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
    还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
    仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
    名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

    宾语补足语句型:
    和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
    因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
    但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
    既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
    动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
    宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

    双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

    在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。
    */

    if (VerbBox1 == "")//没有动词
    {
        return "只有性质状态";//只有性质状态的句型
    }
    else if (VerbBox1 != "" && VerbBox2 == "")//有1个动词
    {
        if (VerbBox1 == "给" || VerbBox1 == "送" || VerbBox1 == "送给" || VerbBox1 == "教")//双宾语句型的常见动词(标志词)
        {
            return "双宾语";//双宾语句型
        }
        else
        {
            return "主谓宾";//主谓宾句型
        }
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//有2个动词
    {
        return "宾语补足语";//宾语补足语句型
    }
    else
    {
        return "其它";
    }
}

}

第三章

省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。

名词合并:
名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
合并方法:如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。

动词合并:
例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词。

动词前面是否有否定词,也很重要。
例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mono.Data.Sqlite;

public class sqlitecon : MonoBehaviour
{
public TMP_Text tmpText;//输出框对象
string ShowText;//输出框的内容
string[] noun = new string[7128];//名词数组,名词数量7128
string[] verb = new string[5886];//动词数组,动词数量5886
int i = 0;//数组用的循环变量
public TMP_InputField inputField;//输入框对象
string shuru = "";//输入框的内容

string FindSubject = "";//找到的主语
string FindVerb = "";//找到的谓语动词
string FindObject = "";//找到的宾语
string FindBuVerb = "";//宾语补足语的动词
string FindBuNoun = "";//宾语补足语的名词
string FindJianObject = "";//找到的间接宾语
string FindZhiObject = "";//找到的直接宾语

string SentenceType = "";//句型
string yutai = "";//语态:主动语态还是被动语态
string VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定

string NounBox1 = "";//名词槽1
string NounBox2 = "";//名词槽2
string NounBox3 = "";//名词槽3
string NounBox4 = "";//名词槽4

string VerbBox1 = "";//动词槽1
string VerbBox2 = "";//动词槽2
string VerbBox3 = "";//动词槽3
string VerbBox4 = "";//动词槽4

// Start is called before the first frame update
void Start()
{
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    dbConnection.Close();
}

// Update is called once per frame
void Update()
{

}

void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的值

    //找谓语动词
    string jieguo = "不包含";//默认值是不包含动词
    int m = verb.Length;//动词数组的长度,也就是有多少个动词

    VerbBox1 = "";
    VerbBox2 = "";
    VerbBox3 = "";
    VerbBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (shuru.Contains(verb[n]))//包含动词
        {
            if (VerbJudge(shuru,verb[n]) == true)//是动词,不是名词
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
                VerbCover(shuru,verb[n]);//把动词放入动词槽里,看看有几个动词
                VerbOrder();//动词排序
                VerbJoin();//动词结合
            }
        }
    }

    if(jieguo == "包含")//包含动词
    {
        VerbRateJudge();//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
        SentenceType = SentenceJudge();//判断句型(仅从动词情况来判断句型,还不是完全清楚的判断,之后还需进一步判断)
        SplitSentence();
    }
}

void SplitSentence()
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string word = "嘲笑";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词语的起始位置
    int LastIndex = 0;//指定词语最后一个字符在全句中的位置
    int jie = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    //计算指定字符在全句中的位置
    index = str.IndexOf(word) + 1;//默认从0计算,例如第2个字符,显示为1,而不是2。为了调整为1开始计算,所以加1
    //计算指定词语最后一个字符在全句中的位置
    LastIndex = str.IndexOf(word) + word.Length;

    //截取第3个字符右边的1个字符
    Substring(开始位置, 向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符

    //截取指定字符右边的全部字符
    jie = chang - LastIndex;//截取长度 = 全句长度 - 指定词语最后一个字符的位置长度
    res = str.Substring(LastIndex, jie);
    res = str.Substring(str.IndexOf(word) + word.Length, str.Length - (str.IndexOf(word) + word.Length));//展开形式

    //截取指定字符左边的全部字符
    res = str.Substring(0, index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0, str.IndexOf(word));//变化形式

    //截取两个指定字符之间的全部字符
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    以上注释掉的内容,只是解释原理,下面是运行的程序:
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    //也可能找到一个动词(主谓宾句型),也可能找到两个动词(宾语补足语句型)
    if (VerbBox1 != "" && VerbBox2 == "")//只找到1个动词,那就是谓语动词
    {
        FindVerb = VerbBox1;
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//找到2个动词
    {
        FindVerb = VerbBox1;//位次在前面的动词是谓语动词
        FindBuVerb = VerbBox2;//位次在后面的动词是宾语补足语动词
    }

    LeftPart = shuru.Substring(0, shuru.IndexOf(FindVerb));
    RightPart = shuru.Substring(shuru.IndexOf(FindVerb) + FindVerb.Length, shuru.Length - (shuru.IndexOf(FindVerb) + FindVerb.Length));

    /*
    例如句子(shuru)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);
    UnityEngine.Debug.Log(LeftPart);
    UnityEngine.Debug.Log(RightPart);
    */

    /*
    省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
    被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
    被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
    程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
    但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
    简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
    如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
    那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。
    */
    yutai = "主动";//默认主动语态
    if (SentenceType == "主谓宾" && shuru.Contains("被"))//语句中包含“被”字
    {
        if (shuru.Contains("被子") == false && shuru.Contains("被褥") == false)//语句中包含“被”字,但不是“被子”这个名词,才能指被动语态的“被”字
        {
            yutai = "被动";//被动语态
        }
        else
        {
            yutai = "主动";//主动语态
        }
    }
    else//语句中没有包含“被”字
    {
        yutai = "主动";//主动语态
    }

    if (LeftPart != "")//谓语动词左边句有内容
    {
        if (yutai == "主动")//主动语态
        {
            FindSubject = SearchNoun(LeftPart);//在谓语动词左边句找名词(主语)
        }
        else if (yutai == "被动")//被动语态
        {
            string bei = "被";
            string BeiLeft = "";
            string BeiRight = "";

            //被字左边句
            BeiLeft = LeftPart.Substring(0, LeftPart.IndexOf(bei));
            FindObject = SearchNoun(BeiLeft);//被字左边句的名词是宾语
            //被字右边句
            BeiRight = LeftPart.Substring(LeftPart.IndexOf(bei) + bei.Length, LeftPart.Length - (LeftPart.IndexOf(bei) + bei.Length));
            FindSubject = SearchNoun(BeiRight);//被字右边句的名词是主语
            //如果没有主语,就填补“事物”这个词作为主语,毕竟被动语态经常没有主语
            if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
            {
                FindSubject = "事物";
            }
        }
    }

    //如果省略主语,则填补省略的主语
    if (yutai == "主动")
    {
        if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
        {
            FindSubject = "你";//默认填补“你”字做主语
        }
    }

    if (SentenceType == "双宾语")//双宾语句型
    {
        FindObject = SearchNoun(RightPart);//找名词

        //谓语动词右边句里,没有第二个宾语名词,那就不是双宾语
        //例如虽然有双宾语句的标志动词“教”字,但他教我数学,是双宾语句,而他教书,是主谓宾句型
        if (NounBox2 == "")
        {
            SentenceType = "主谓宾";
        }
        else
        {
            ShowResult();//显示最终输出结果
        }
    }

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        if (RightPart != "")
        {
            if (yutai == "主动")
            {
                FindObject = SearchNoun(RightPart);//在谓语动词右边句找名词(宾语)
            }
        }

        ShowResult();//显示最终输出结果
    }

    if (SentenceType == "宾语补足语")//宾语补足语句型
    {
        //谓语动词到宾语补足语动词之间的部分里的名词,是宾语名词
        string temp = "";
        //截取谓语动词FindVerb和宾语补足语动词FindBuVerb之间的部分
        temp = shuru.Substring(shuru.IndexOf(FindVerb) + FindVerb.Length, shuru.IndexOf(FindBuVerb) - (shuru.IndexOf(FindVerb) + FindVerb.Length));
        FindObject = SearchNoun(temp);//找名词
        //宾语补足语右边句的名词,是宾语补足语名词,而不是宾语名词
        int WordLastChar = shuru.IndexOf(FindBuVerb) + FindBuVerb.Length;//宾语补足语动词最后一个字符的位置
        if (WordLastChar < shuru.Length)//宾语补足语动词最后一个字符的位置没有到全句末尾,就是说宾语补足语动词后面还有内容,那就是宾语补足语名词
        {
            //截取宾语补足语动词右边的内容
            FindBuNoun = shuru.Substring(shuru.IndexOf(FindBuVerb) + FindBuVerb.Length, shuru.Length - (shuru.IndexOf(FindBuVerb) + FindBuVerb.Length));
        }

        ShowResult();//显示最终输出结果
    }

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

string SearchNoun(string PartSentence)
{
    //找名词
    string jieguo = "不包含";//默认值是不包含
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    NounBox1 = "";
    NounBox2 = "";
    NounBox3 = "";
    NounBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字,才算是名词,否则是名词所有格
            {
                NounCover(noun[n]);
            }
        }
    }

    if (jieguo == "包含")//找到了名词
    {
        NounOrder();//名词排序
        //名词要先排序,才能合并名词,否则“足球”和“学校”的顺序如果变成“学校”和“足球”,那就合并成“学校足球”这个词了,而不是“足球学校”

        //如果双宾语句型进行名词合并,就可能会把间接宾语名词和直接宾语名词合并到一起,成为一个名词,就不对了
        if (SentenceType != "双宾语")//不是双宾语句型
        {
            NounJoin();//名词合并,例如把“足球”和“学校”合并成“足球学校”这一个名词
        }
        else if (SentenceType == "双宾语")//是双宾语句型
        {
            //但是如果现在处理的是双宾语结构的谓语动词左边句,也就是处理主语,还是可以名词合并的
            if (shuru.IndexOf(NounBox1) < shuru.IndexOf(FindVerb))
            {
                NounJoin();//名词合并
            }
        }

        return NounBox1;
    }
    else
    {
        return "";
    }
}

void NounCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(NounBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (NounBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        NounBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (NounBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(NounBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (NounBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(NounBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (NounBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        NounBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (NounBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(NounBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (NounBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(NounBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (NounBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        NounBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (NounBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(NounBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (NounBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(NounBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (NounBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        NounBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (NounBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(NounBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (NounBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(NounBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    /*
    “足球”这个词,会找到三个名词:足、球、足球。
    先找到第一个词:足,放入NounBox1。
    再找到第二个词:球,放入NounBox2。
    再找到第三个词:足球,会覆盖NounBox1的“足”字,但却无法覆盖NounBox2的球字。
    因此程序做一些改进。

    但如果幸运的:
    先找到第一个词:足球,放入NounBox1。
    再找到第二个词:足,被NounBox1“足球”这个词吸收,不会进入到NounBox2。
    再找到第三个词:球,被NounBox1“足球”这个词吸收,也不会进入到NounBox2。
    那么就不用执行下面这段程序了。
    先找到那个词是不确定的,词库词语可能按笔画排序,也可能按首字母排序,就不知道先找到那个词了。

    如果输入的是“皮球”这个词,而词库里没有“皮球”这个词,但有“皮”字和“球”字这两个词。
    那么,NounBox1是“皮”字,NounBox2是“球”字,或NounBox1是“球”字,NounBox2是“皮”字,没有覆盖和吸收。
    */
    if (NounBox1.Contains(NounBox2))//NounBox1包含了NounBox2,例如“足球”包含“球”字
    {
        NounBox2 = "";
        if (NounBox3 != "")
        {
            NounBox2 = NounBox3;
            NounBox3 = "";
        }
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox2.Contains(NounBox3))//NounBox2包含了NounBox3
    {
        NounBox3 = "";
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox3.Contains(NounBox4))//NounBox3包含了NounBox4
    {
        NounBox4 = "";
    }
}

void VerbCover(string str,string FindWord)
{
    if (VerbBox1 == "" && FindWord != "")//动词槽还是空的,说明这是找到的第一个词
    {
        VerbBox1 = FindWord;//找到的第1个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽2了
    }
    else if (VerbBox1 != "" && FindWord != "")//动词槽1已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox1))//覆盖:例如找到的词(FindWord)是敲打,动词槽1(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“敲打”覆盖“打”
            FindWord = "";//置空,免得填到动词槽2了
        }
        else if (VerbBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽1(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,不要这个词了,免得填到动词槽2了
        }
    }

    if (VerbBox2 == "" && FindWord != "")//动词槽2是空的,FindWord经过动词槽1,没有覆盖或吸收,说明FindWord和动词槽1的词无关,例如FindWord是喜欢
    {
        VerbBox2 = FindWord;//找到的第2个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽3了
    }
    else if (VerbBox2 != "" && FindWord != "")//动词槽2已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox2))//覆盖:例如找到的词(FindWord)是敲打,动词槽2(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (VerbBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽2(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (VerbBox3 == "" && FindWord != "")//动词槽3是空的,FindWord经过动词槽1和2,没有覆盖或吸收,说明FindWord和动词槽1、2的词无关,例如FindWord是喜欢
    {
        VerbBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (VerbBox3 != "" && FindWord != "")//动词槽3已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox3))//覆盖:例如找到的词(FindWord)是敲打,动词槽3(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (VerbBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽3(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (VerbBox4 == "" && FindWord != "")//动词槽4是空的,FindWord经过动词槽1、2、3,没有覆盖或吸收,说明FindWord和动词槽1、2、3的词无关,例如FindWord是喜欢
    {
        VerbBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (VerbBox4 != "" && FindWord != "")//动词槽4已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox4))//覆盖:例如找到的词(FindWord)是敲打,动词槽4(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (VerbBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽4(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空
        }
    }

    /*
    “敲打”这个词,会找到三个动词:敲、打、敲打
    先找到第一个词:敲,放入VerbBox1
    再找到第二个词:打,放入VerbBox2
    再找到第三个词:敲打,会覆盖VerbBox1的“敲”字,但却无法覆盖VerbBox2的“打”字
    因此程序做一些改进。 
    */
    if (VerbBox1.Contains(VerbBox2))//VerbBox1包含了VerbBox2
    {
        VerbBox2 = "";
        if (VerbBox3 != "")
        {
            VerbBox2 = VerbBox3;
            VerbBox3 = "";
        }
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox2.Contains(VerbBox3))//VerbBox2包含了VerbBox3
    {
        VerbBox3 = "";
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox3.Contains(VerbBox4))//VerbBox3包含了VerbBox4
    {
        VerbBox4 = "";
    }
}

bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上注释掉的内容只是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }

}

bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   吹     |   l1    |      电      |
    +----------+---------+--------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上注释掉的内容,只是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

string SentenceJudge()
{
    /*
    判断句型:
    基本单句有六种句型:
    只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
    主语(动作执行者)-谓语(动作):张三摔倒。
    主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
    主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
    双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
    宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
    前面只说了主谓宾句型,还要处理其它句型。

    双宾语句型:
    双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
    但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
    双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
    那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
    还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
    仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
    名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

    宾语补足语句型:
    和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
    因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
    但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
    既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
    动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
    宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

    双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

    在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。
    */

    if (VerbBox1 == "")//没有动词
    {
        return "只有性质状态";//只有性质状态的句型
    }
    else if (VerbBox1 != "" && VerbBox2 == "")//有1个动词
    {
        if (VerbBox1 == "给" || VerbBox1 == "送" || VerbBox1 == "送给" || VerbBox1 == "教")//双宾语句型的常见动词(标志词)
        {
            return "双宾语";//双宾语句型
        }
        else
        {
            return "主谓宾";//主谓宾句型
        }
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//有2个动词
    {
        return "宾语补足语";//宾语补足语句型
    }
    else
    {
        return "其它";
    }
}

void NounOrder()
{
    //名词排序
    if (NounBox1 != "" && NounBox2 != "")//招到了2个名词,放在NounBox1和NounBox2
    {
        string temp = "";//临时变量
        if (shuru.IndexOf(NounBox1) > shuru.IndexOf(NounBox2))//如果NounBox1的名词在句子中的位置大于NounBox2的名词在句子中的位置
        {
            //交换位置,在句子中位置小的名词放前面,从而确保双宾语句型时,NounBox1放的是间接宾语,NounBox2放的是直接宾语,毕竟间接宾语在直接宾语前面
            temp = NounBox1;
            NounBox1 = NounBox2;
            NounBox2 = temp;
        }
        FindJianObject = NounBox1;
        FindZhiObject = NounBox2;
    }
}

void NounJoin()
{
    /*
    名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
    前面说了判断两个字符之间的内容,如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。
    示例:
    //截取两个指定字符之间的全部字符
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string res = "";//结果
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式
    if (res == "")
    {
        UnityEngine.Debug.Log("连续");
    }
    else
    {
        UnityEngine.Debug.Log("不连续");
    }
    */
    
    string res;
    //判断NounBox1和NounBox2的名词是否需要合并
    if (NounBox1 != "" && NounBox2 != "")
    {
        res = "";
        //判断NounBox1和NounBox2之间是否有内容,如果没内容(res为空),就说明NounBox1和NounBox2是连续的名词(中间没有字符间隔),需要合并
        res = shuru.Substring(shuru.IndexOf(NounBox1) + NounBox1.Length, shuru.IndexOf(NounBox2) - (shuru.IndexOf(NounBox1) + NounBox1.Length));
        if (res == "")
        {
            NounBox1 = NounBox1 + NounBox2;//名词合并
            NounBox2 = "";//合并后,置空
            if (NounBox3 != "")
            {
                NounBox2 = NounBox3;//填补置空的值,否则NounBox1有值,NounBox2为空,NounBox3又有值,就间隔了
                NounBox3 = "";//合并后,置空
                if (NounBox4 != "")
                {
                    NounBox3 = NounBox4;
                    NounBox4 = "";//合并后,置空
                }
            }
        }
    }

    /*
    //判断NounBox2和NounBox3的名词是否需要合并
    if (NounBox2 != "" && NounBox3 != "")
    {
        res = "";
        //判断NounBox2和NounBox3之间是否有内容,如果没内容(res为空),就说明NounBox2和NounBox3是连续的名词,需要合并
        res = shuru.Substring(shuru.IndexOf(NounBox2) + NounBox2.Length, shuru.IndexOf(NounBox3) - (shuru.IndexOf(NounBox2) + NounBox2.Length));
        if (res == "")
        {
            NounBox2 = NounBox2 + NounBox3;//名词合并
            NounBox3 = "";//合并后,置空
            if (NounBox4 != "")
            {
                NounBox3 = NounBox4;//填补置空的值
                NounBox4 = "";//合并后,置空
            }
        }
    }

    //判断NounBox3和NounBox4的名词是否需要合并
    if (NounBox3 != "" && NounBox4 != "")
    {
        res = "";
        //判断NounBox3和NounBox4之间是否有内容,如果没内容(res为空),就说明NounBox3和NounBox4是连续的名词,需要合并
        res = shuru.Substring(shuru.IndexOf(NounBox3) + NounBox3.Length, shuru.IndexOf(NounBox4) - (shuru.IndexOf(NounBox3) + NounBox3.Length));
        if (res == "")
        {
            NounBox3 = NounBox3 + NounBox4;//名词合并
            NounBox4 = "";//合并后,置空
        }
    }
    */
}

void VerbOrder()
{
    /*
    动词排序:
    如果不排序会怎样?句子中找到的第一个动词,可能不是谓语动词,而是宾语补足语动词,以宾语补足语动词分割句子,就错了。
    谓语动词和宾语补足语动词,先找到哪个,取决于这两个词,谁在动词表前面排序,而动词的排序是不可知的,或许按笔划排序,或者按首字母排序
    */
    string temp = "";//临时变量
    if (VerbBox1 != "" && VerbBox2 != "")//招到了个动词,放在VerbBox1和VerbBox2
    {
        if (shuru.IndexOf(VerbBox1) > shuru.IndexOf(VerbBox2))//如果VerbBox1的动词在句子中的位置大于VerbBox2的动词在句子中的位置
        {
            //交换位置,在句子中位置小动词的放前面,从而确保VerbBox1放的是谓语动词,而宾语补足语动词放到VerbBox2
            temp = VerbBox1;
            VerbBox1 = VerbBox2;
            VerbBox2 = temp;
        }

    }
    if (VerbBox3 != "")
    {
        if (shuru.IndexOf(VerbBox1) > shuru.IndexOf(VerbBox3))
        {
            temp = VerbBox1;
            VerbBox1 = VerbBox3;
            VerbBox3 = temp;
        }
        if (shuru.IndexOf(VerbBox2) > shuru.IndexOf(VerbBox3))
        {
            temp = VerbBox2;
            VerbBox2 = VerbBox3;
            VerbBox3 = temp;
        }
    }
    FindVerb = VerbBox1;
}

void VerbJoin()
{
    //动词合并:例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词
    string res;
    //判断VerbBox1和VerbBox2的动词是否需要合并
    if (VerbBox1 != "" && VerbBox2 != "")
    {
        res = "";
        //判断VerbBox1和VerbBox2之间是否有内容,如果没内容(res为空),就说明VerbBox1和VerbBox2是连续的动词(中间没有字符间隔),需要合并
        res = shuru.Substring(shuru.IndexOf(VerbBox1) + VerbBox1.Length, shuru.IndexOf(VerbBox2) - (shuru.IndexOf(VerbBox1) + VerbBox1.Length));
        if (res == "")
        {
            VerbBox1 = VerbBox1 + VerbBox2;//名词合并
            FindVerb = VerbBox1;
            VerbBox2 = "";//合并后,置空
            if (VerbBox3 != "")
            {
                VerbBox2 = VerbBox3;//填补置空的值,否则VerbBox1有值,VerbBox2为空,VerbBox3又有值,就间隔了
                VerbBox3 = "";//合并后,置空
                if (VerbBox4 != "")
                {
                    VerbBox3 = VerbBox4;
                    VerbBox4 = "";//合并后,置空
                }
            }
        }
    }

}

void VerbRateJudge()
{
    /*
    动词前面是否有否定词,也很重要。
    例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
    谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
    还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
    因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
    但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
    那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
    这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 1, 1);
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 2, 1);
    */

    VerbRate = "肯定";//默认值:肯定
    string temp = "";//临时变量

    //先判断谓语动词左边的1个字符,是否是否定词
    temp = shuru.Substring(shuru.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不"))
    {
        VerbRate = "否定";
    }
    else if(temp.Contains("别"))
    {
        VerbRate = "否定";
    }

    //判断谓语动词左边的2个字符,是否是否定词
    temp = shuru.Substring(shuru.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不要"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不能"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("可能"))
    {
        VerbRate = "不确定";
    }
    else if (temp.Contains("或许"))
    {
        VerbRate = "不确定";
    }

    //判断谓语动词左边的3个字符,是否是否定词
    temp = shuru.Substring(shuru.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不可以"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不应该"))
    {
        VerbRate = "否定";
    }
}

//显示最终输出结果
void ShowResult()
{
    //tmpText.text = "";//Text Mesh Pro控件显示文字

    UnityEngine.Debug.Log("句型:" + SentenceType);

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("语态:" + yutai);
    }
    else if (SentenceType == "双宾语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("间接宾语:" + FindJianObject);
        UnityEngine.Debug.Log("直接宾语:" + FindZhiObject);
    }
    else if (SentenceType == "宾语补足语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("宾语补足语动词:" + FindBuVerb);
        UnityEngine.Debug.Log("宾语补足语名词:" + FindBuNoun);
    }
    else if (SentenceType == "只有性质状态")
    {
        UnityEngine.Debug.Log("只有性质状态:" + shuru);
    }

    UnityEngine.Debug.Log("动词发生概率:" + VerbRate);

    //清空变量
    FindSubject = "";
    FindVerb = "";
    FindObject = "";
    FindBuVerb = "";
    FindBuNoun = "";
    FindJianObject = "";
    FindZhiObject = "";
    yutai = "";
}

}

第四章
在这一章:
第一,一次可以输入多句话,但只能用逗号或句号隔开,不能用问号和感叹号分隔句子。
第二,对主谓宾结构可以分析出定语(形容词、数词、名词所有格),但双宾语句型和宾语补足语句型,还没有做定语分析程序,而且数词只能用阿拉伯数字,也就是1、2、3这类数字,还不能用汉字型数字。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//Canvas框显示输入框和输出框所需
using TMPro;//Text Mesh Pro文字控件所需
using Mono.Data.Sqlite;//连接sqlite数据库所需
using System.Text.RegularExpressions;//正则表达式找出数字所需

public class sqlitecon : MonoBehaviour
{
//输入和输出
public TMP_InputField inputField;//输入框对象(把层级面板上的输入框控件拖动到此框里)
string shuru = "";//输入框内容
//public TMP_Text tmpText;//输出框对象(把层级面板上的输出框控件拖动到此框里)
//string mes;//输出框内容
//词库
string[] noun = new string[7128];//名词数组,名词数量7128(数据库增加名词后,此处也要修改,以免造成溢出)
string[] verb = new string[5886];//动词数组,动词数量5886(数据库增加动词后,此处也要修改,以免造成溢出)
string[] adj = new string[1777];//形容词数组,形容词数量1777(数据库增加形容词后,此处也要修改,以免造成溢出)
int i = 0;//数组用的循环变量
//按标点符号分割句子
string dan = "";//按标点符号分割出的基本单句
string[] danju = new string[100];//单句的数组储存
int dan_num = 1;//第几个单句
//基本单句的语法结构
string FindSubject = "";//主语
string FindVerb = "";//谓语动词
string FindObject = "";//宾语
string FindBuVerb = "";//宾语补足语的动词
string FindBuNoun = "";//宾语补足语的名词
string FindJianObject = "";//间接宾语
string FindZhiObject = "";//直接宾语
//名词所有格(例如张三的猫,张三就是名词所有格,“的”字就不写了)
string SubjectSuoyouge = "";//主语的名词所有格
string ObjectSuoyouge = "";//宾语的名词所有格
//string JianSuoyouge = "";//间接宾语的名词所有格
//string ZhiSuoyouge = "";//直接宾语的名词所有格
//string BuSuoyouge = "";//宾语补足语的名词所有格
string TempSuoyouge = "";//临时存放名词所有格
//形容词
string SubjectAdj = "";//主语的形容词
string ObjectAdj = "";//宾语的形容词
//string JianAdj = "";//间接宾语的形容词
//string ZhiAdj = "";//直接宾语的形容词
//string BuAdj = "";//宾语补足语的形容词
//数词
string SubjectNum = "";//主语的数词
string ObjectNum = "";//宾语的数词
//string JianNum = "";//间接宾语的数词
//string ZhiNum = "";//直接宾语的数词
//string BuNum = "";//宾语补足语的数词
//语法结构的相关描述
string SentenceType = "";//句型
string yutai = "";//语态:主动语态还是被动语态
string VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
//名词槽(名词之间相互覆盖时用)
string NounBox1 = "";//名词槽1
string NounBox2 = "";//名词槽2
string NounBox3 = "";//名词槽3
string NounBox4 = "";//名词槽4
//动词槽(动词之间相互覆盖时用)
string VerbBox1 = "";//动词槽1
string VerbBox2 = "";//动词槽2
string VerbBox3 = "";//动词槽3
string VerbBox4 = "";//动词槽4

// Start is called before the first frame update
void Start()
{
    ciku();//填充词库
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应(按回车键发送)
}

// Update is called once per frame
void Update()
{

}

//填充词库(数据库的词库填充到数组中)
void ciku()
{
    //生成游戏后,需要把sqlite数据库复制到生成的游戏的文件夹里,那个文件夹自动生成的这个数据库是0kb,无效的,需要重新复制过去
    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    //填充形容词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM adj";//sql指令
    //第二步:执行指令
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        adj[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示形容词数量

    dbConnection.Close();//关闭数据库连接
}

//输入完成后,按回车键发送,便开始执行此函数
void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的内容
    SplitSay();//按标点符号,分割输入内容
}

//按标点符号,分割输入内容,分割成基本单句
void SplitSay()
{
    /*
    输入的内容可能是一大段内容,需要分割成一个个基本单句,从而逐一处理。
    基本单句就是主语-谓语-宾语,或主语-谓语-间接宾语-直接宾语,或主语-谓语-宾语-宾语补足语,这类语法上的基本单句。
    那就需要按逗号分割句子,按句号分割句子,才能拆分成一个个这样的基本单句。

    按逗号分割句子:
    string str = "早晨,中午,下午";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符,分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    按逗号和句号分割句子:
    string str = "早晨,中午。下午,傍晚";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        string word2 = "。";
        string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
        foreach (string part2 in shuzu2)
        {
            UnityEngine.Debug.Log(part2);
        }
    }

    计算标点符号的数量:
    string str = "早晨,中午。下午,傍晚";
    string temp = "";

    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = str.Length;//句子长度

    temp = str.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量

    temp = str.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    以上注释掉的内容,只是解释说明,下面才是运行的程序:
    */

    //计算标点符号的数量
    string temp = "";
    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = shuru.Length;//句子长度
    //计算逗号的数量
    temp = shuru.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量
    //计算句号的数量
    temp = shuru.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    //按标点符号分割句子
    if (dou > 0 || ju > 0)//逗号大于0或句号大于0,就是输入的内容有标点符号
    {
        string word = ",";//分割符:中文的逗号
        string[] shuzu = shuru.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
        foreach (string part in shuzu)//逐个处理
        {
            string word2 = "。";//分割符:中文的句号
            string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
            foreach (string part2 in shuzu2)//逐个处理
            {
                dan = part2;//基本单句已经分割出来了,在part2里,并赋值给dan(基本单句)
                danju[dan_num - 1] = part2;//数组从0开始计算,而danju从1开始计算,所以换算上要减1
                ClearData();//清除上次的变量数据
                //UnityEngine.Debug.Log("单句:" + dan);
                SearchVerb(dan);//找谓语动词(这是单句处理的第一步)
                dan = "";
                dan_num++;
            }
        }
    }
    else//输入的内容,没有标点符号
    {
        if (shuru != "")//有输入的内容
        {
            dan = shuru;//输入的内容就是一个基本单句
            danju[0] = shuru;
            SearchVerb(dan);//找谓语动词
            dan = "";
        }
    }
}

//清除上次循环(基本单句处理)的变量数据
void ClearData()
{
    FindSubject = "";//主语
    FindVerb = "";//谓语动词
    FindObject = "";//宾语
    FindBuVerb = "";//宾语补足语的动词
    FindBuNoun = "";//宾语补足语的名词
    FindJianObject = "";//间接宾语
    FindZhiObject = "";//直接宾语
    SubjectSuoyouge = "";//主语的名词所有格
    ObjectSuoyouge = "";//宾语的名词所有格
    TempSuoyouge = "";//临时存放名词所有格
    SubjectAdj = "";//主语的形容词
    ObjectAdj = "";//宾语的形容词
    SubjectNum = "";//主语的数词
    ObjectNum = "";//宾语的数词
    SentenceType = "";//句型
    yutai = "";//语态:主动语态还是被动语态
    VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
    NounBox1 = "";//名词槽1
    NounBox2 = "";//名词槽2
    NounBox3 = "";//名词槽3
    NounBox4 = "";//名词槽4
    VerbBox1 = "";//动词槽1
    VerbBox2 = "";//动词槽2
    VerbBox3 = "";//动词槽3
    VerbBox4 = "";//动词槽4
    i = 0;
}

//找谓语动词
void SearchVerb(string str)
{
    string jieguo = "不包含";//默认值是不包含动词
    int m = verb.Length;//动词数组的长度,也就是有多少个动词

    VerbBox1 = "";
    VerbBox2 = "";
    VerbBox3 = "";
    VerbBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (str.Contains(verb[n]))//包含动词
        {
            if (VerbJudge(str, verb[n]) == true)//是动词,不是名词
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
                VerbCover(str, verb[n]);//把动词放入动词槽里,看看有几个动词
                VerbOrder();//动词排序
                VerbJoin();//动词结合
            }
        }
    }

    if (jieguo == "包含")//包含动词
    {
        VerbRateJudge();//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
        SentenceType = SentenceJudge();//判断句型(仅从动词情况来判断句型,还不是完全清楚的判断,之后还需进一步判断)
        SplitSentence();//以谓语动词为分割符,来分割句子
    }
}

//以谓语动词为分割符,来分割句子
void SplitSentence()
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string word = "嘲笑";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词语的起始位置
    int LastIndex = 0;//指定词语最后一个字符在全句中的位置
    int jie = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    //计算指定字符在全句中的位置
    index = str.IndexOf(word) + 1;//默认从0计算,例如第2个字符,显示为1,而不是2。为了调整为1开始计算,所以加1
    //计算指定词语最后一个字符在全句中的位置
    LastIndex = str.IndexOf(word) + word.Length;

    //截取第3个字符右边的1个字符
    Substring(开始位置, 向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符

    //截取指定字符右边的全部字符
    jie = chang - LastIndex;//截取长度 = 全句长度 - 指定词语最后一个字符的位置长度
    res = str.Substring(LastIndex, jie);
    res = str.Substring(str.IndexOf(word) + word.Length, str.Length - (str.IndexOf(word) + word.Length));//展开形式

    //截取指定字符左边的全部字符
    res = str.Substring(0, index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0, str.IndexOf(word));//变化形式

    //截取两个指定字符之间的全部字符
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    以上注释掉的内容,只是解释原理,下面是运行的程序:
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    //也可能找到一个动词(主谓宾句型),也可能找到两个动词(宾语补足语句型)
    if (VerbBox1 != "" && VerbBox2 == "")//只找到1个动词,那就是谓语动词
    {
        FindVerb = VerbBox1;
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//找到2个动词
    {
        FindVerb = VerbBox1;//位次在前面的动词是谓语动词
        FindBuVerb = VerbBox2;//位次在后面的动词是宾语补足语动词
    }

    //谓语动词左边句(LeftPart)和谓语动词右边句(RightPart)是一个重要的转折,为以后的句子处理奠定了基础
    LeftPart = dan.Substring(0, dan.IndexOf(FindVerb));
    RightPart = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.Length - (dan.IndexOf(FindVerb) + FindVerb.Length));

    /*
    例如句子(dan)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);//谓语动词
    UnityEngine.Debug.Log(LeftPart);//谓语动词的左边句
    UnityEngine.Debug.Log(RightPart);//谓语动词的右边句
    */

    /*
    省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
    被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
    被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
    程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
    但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
    简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
    如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
    那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。
    */
    yutai = "主动";//默认主动语态
    if (SentenceType == "主谓宾" && dan.Contains("被"))//语句中包含“被”字
    {
        if (dan.Contains("被子") == false && dan.Contains("被褥") == false)//语句中包含“被”字,但不是“被子”这个名词,才能指被动语态的“被”字
        {
            yutai = "被动";//被动语态
        }
        else
        {
            yutai = "主动";//主动语态
        }
    }
    else//语句中没有包含“被”字
    {
        yutai = "主动";//主动语态
    }

    //对谓语动词左边句(LeftPart)的处理
    if (LeftPart != "")//谓语动词左边句有内容
    {
        if (yutai == "主动")//主动语态
        {
            //找名词(主语)和名词所有格
            FindSubject = SearchNoun(LeftPart);//在谓语动词左边句找名词(主语)
            if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
            {
                SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                TempSuoyouge = "";//置空
            }
            //找形容词(主语的形容词)
            SubjectAdj = SearchAdj(LeftPart);
            //找数词
            SubjectNum = SearchNum(LeftPart);
        }
        else if (yutai == "被动")//被动语态
        {
            string bei = "被";
            string BeiLeft = "";
            string BeiRight = "";

            //被字左边句
            BeiLeft = LeftPart.Substring(0, LeftPart.IndexOf(bei));
            if (BeiLeft != "")
            {
                FindObject = SearchNoun(BeiLeft);//被字左边句的名词是宾语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(BeiLeft);
                //找数词
                ObjectNum = SearchNum(BeiLeft);
            }

            //被字右边句
            BeiRight = LeftPart.Substring(LeftPart.IndexOf(bei) + bei.Length, LeftPart.Length - (LeftPart.IndexOf(bei) + bei.Length));
            
            if (BeiRight != "")
            {
                FindSubject = SearchNoun(BeiRight);//被字右边句的名词是主语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(主语的形容词)
                SubjectAdj = SearchAdj(BeiRight);
                //找数词
                SubjectNum = SearchNum(BeiRight);
            }
            //如果没有主语,就填补“事物”这个词作为主语,毕竟被动语态经常没有主语
            if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
            {
                FindSubject = "事物";
            }
        }
    }

    //如果省略主语,则填补省略的主语
    if (yutai == "主动")
    {
        if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
        {
            FindSubject = "你";//默认填补“你”字做主语
        }
    }

    //对谓语动词右边句(RightPart)的处理
    if (SentenceType == "双宾语")//双宾语句型
    {
        FindObject = SearchNoun(RightPart);//找名词

        //谓语动词右边句里,没有第二个宾语名词,那就不是双宾语
        //例如虽然有双宾语句的标志动词“教”字,但他教我数学,是双宾语句,而他教书,是主谓宾句型
        if (NounBox2 == "")
        {
            SentenceType = "主谓宾";
        }
        else
        {
            ShowResult();//显示最终输出结果
        }
    }

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        if (RightPart != "")
        {
            if (yutai == "主动")
            {
                //找名词和名词所有格
                FindObject = SearchNoun(RightPart);//在谓语动词右边句找名词(宾语)
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }

                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(RightPart);
                //找数词
                ObjectNum = SearchNum(RightPart);
            }
            
        }

        ShowResult();//显示最终输出结果
    }

    if (SentenceType == "宾语补足语")//宾语补足语句型
    {
        //谓语动词到宾语补足语动词之间的部分里的名词,是宾语名词
        string temp = "";
        //截取谓语动词FindVerb和宾语补足语动词FindBuVerb之间的部分
        temp = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.IndexOf(FindBuVerb) - (dan.IndexOf(FindVerb) + FindVerb.Length));
        FindObject = SearchNoun(temp);//找名词
        if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
        {
            ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
            TempSuoyouge = "";//置空
        }
        //宾语补足语右边句的名词,是宾语补足语名词,而不是宾语名词
        int WordLastChar = dan.IndexOf(FindBuVerb) + FindBuVerb.Length;//宾语补足语动词最后一个字符的位置
        if (WordLastChar < dan.Length)//宾语补足语动词最后一个字符的位置没有到全句末尾,就是说宾语补足语动词后面还有内容,那就是宾语补足语名词
        {
            //截取宾语补足语动词右边的内容
            FindBuNoun = dan.Substring(dan.IndexOf(FindBuVerb) + FindBuVerb.Length, dan.Length - (dan.IndexOf(FindBuVerb) + FindBuVerb.Length));
            //以后再写找宾语补足语名词的名词所有格
        }

        ShowResult();//显示最终输出结果
    }

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

//找名词(也包括找名词所有格)
string SearchNoun(string PartSentence)
{
    string jieguo = "不包含";//默认值是不包含
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    NounBox1 = "";
    NounBox2 = "";
    NounBox3 = "";
    NounBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字,才算是名词,否则是名词所有格
            {
                NounCover(noun[n]);
            }
            else//名词右边的第一个字是“的”字,就意味着是名词所有格
            {
                TempSuoyouge = noun[n];//找到的名词所有格
            }
        }
    }

    if (jieguo == "包含")//找到了名词
    {
        NounOrder();//名词排序
        //名词要先排序,才能合并名词,否则“足球”和“学校”的顺序如果变成“学校”和“足球”,那就合并成“学校足球”这个词了,而不是“足球学校”

        //如果双宾语句型进行名词合并,就可能会把间接宾语名词和直接宾语名词合并到一起,成为一个名词,就不对了
        if (SentenceType != "双宾语")//不是双宾语句型
        {
            NounJoin();//名词合并,例如把“足球”和“学校”合并成“足球学校”这一个名词
        }
        else if (SentenceType == "双宾语")//是双宾语句型
        {
            //但是如果现在处理的是双宾语结构的谓语动词左边句,也就是处理主语,还是可以名词合并的
            if (dan.IndexOf(NounBox1) < dan.IndexOf(FindVerb))
            {
                NounJoin();//名词合并
            }
        }

        return NounBox1;
    }
    else
    {
        return "";
    }
}

//名词之间的覆盖
void NounCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(NounBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (NounBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        NounBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (NounBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(NounBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (NounBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(NounBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (NounBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        NounBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (NounBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(NounBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (NounBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(NounBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (NounBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        NounBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (NounBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(NounBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (NounBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(NounBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (NounBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        NounBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (NounBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(NounBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (NounBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(NounBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    /*
    “足球”这个词,会找到三个名词:足、球、足球。
    先找到第一个词:足,放入NounBox1。
    再找到第二个词:球,放入NounBox2。
    再找到第三个词:足球,会覆盖NounBox1的“足”字,但却无法覆盖NounBox2的球字。
    因此程序做一些改进。

    但如果幸运的:
    先找到第一个词:足球,放入NounBox1。
    再找到第二个词:足,被NounBox1“足球”这个词吸收,不会进入到NounBox2。
    再找到第三个词:球,被NounBox1“足球”这个词吸收,也不会进入到NounBox2。
    那么就不用执行下面这段程序了。
    先找到那个词是不确定的,词库词语可能按笔画排序,也可能按首字母排序,就不知道先找到那个词了。

    如果输入的是“皮球”这个词,而词库里没有“皮球”这个词,但有“皮”字和“球”字这两个词。
    那么,NounBox1是“皮”字,NounBox2是“球”字,或NounBox1是“球”字,NounBox2是“皮”字,没有覆盖和吸收。
    */
    if (NounBox1.Contains(NounBox2))//NounBox1包含了NounBox2,例如“足球”包含“球”字
    {
        NounBox2 = "";
        if (NounBox3 != "")
        {
            NounBox2 = NounBox3;
            NounBox3 = "";
        }
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox2.Contains(NounBox3))//NounBox2包含了NounBox3
    {
        NounBox3 = "";
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox3.Contains(NounBox4))//NounBox3包含了NounBox4
    {
        NounBox4 = "";
    }
}

//动词之间的覆盖
void VerbCover(string str,string FindWord)
{
    if (VerbBox1 == "" && FindWord != "")//动词槽还是空的,说明这是找到的第一个词
    {
        VerbBox1 = FindWord;//找到的第1个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽2了
    }
    else if (VerbBox1 != "" && FindWord != "")//动词槽1已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox1))//覆盖:例如找到的词(FindWord)是敲打,动词槽1(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“敲打”覆盖“打”
            FindWord = "";//置空,免得填到动词槽2了
        }
        else if (VerbBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽1(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,不要这个词了,免得填到动词槽2了
        }
    }

    if (VerbBox2 == "" && FindWord != "")//动词槽2是空的,FindWord经过动词槽1,没有覆盖或吸收,说明FindWord和动词槽1的词无关,例如FindWord是喜欢
    {
        VerbBox2 = FindWord;//找到的第2个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽3了
    }
    else if (VerbBox2 != "" && FindWord != "")//动词槽2已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox2))//覆盖:例如找到的词(FindWord)是敲打,动词槽2(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (VerbBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽2(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (VerbBox3 == "" && FindWord != "")//动词槽3是空的,FindWord经过动词槽1和2,没有覆盖或吸收,说明FindWord和动词槽1、2的词无关,例如FindWord是喜欢
    {
        VerbBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (VerbBox3 != "" && FindWord != "")//动词槽3已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox3))//覆盖:例如找到的词(FindWord)是敲打,动词槽3(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (VerbBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽3(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (VerbBox4 == "" && FindWord != "")//动词槽4是空的,FindWord经过动词槽1、2、3,没有覆盖或吸收,说明FindWord和动词槽1、2、3的词无关,例如FindWord是喜欢
    {
        VerbBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (VerbBox4 != "" && FindWord != "")//动词槽4已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox4))//覆盖:例如找到的词(FindWord)是敲打,动词槽4(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (VerbBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽4(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空
        }
    }

    /*
    “敲打”这个词,会找到三个动词:敲、打、敲打
    先找到第一个词:敲,放入VerbBox1
    再找到第二个词:打,放入VerbBox2
    再找到第三个词:敲打,会覆盖VerbBox1的“敲”字,但却无法覆盖VerbBox2的“打”字
    因此程序做一些改进。 
    */
    if (VerbBox1.Contains(VerbBox2))//VerbBox1包含了VerbBox2
    {
        VerbBox2 = "";
        if (VerbBox3 != "")
        {
            VerbBox2 = VerbBox3;
            VerbBox3 = "";
        }
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox2.Contains(VerbBox3))//VerbBox2包含了VerbBox3
    {
        VerbBox3 = "";
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox3.Contains(VerbBox4))//VerbBox3包含了VerbBox4
    {
        VerbBox4 = "";
    }
}

//名词后面是否包含“的”字
bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上注释掉的内容只是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }

}

//判断一个字是动词还是名词
bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   吹     |   l1    |      电      |
    +----------+---------+--------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上注释掉的内容,只是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

//判断句型
string SentenceJudge()
{
    /*
    基本单句有六种句型:
    只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
    主语(动作执行者)-谓语(动作):张三摔倒。
    主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
    主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
    双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
    宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
    前面只说了主谓宾句型,还要处理其它句型。

    双宾语句型:
    双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
    但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
    双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
    那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
    还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
    仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
    名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

    宾语补足语句型:
    和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
    因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
    但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
    既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
    动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
    宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

    双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

    在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。
    */

    if (VerbBox1 == "")//没有动词
    {
        return "只有性质状态";//只有性质状态的句型
    }
    else if (VerbBox1 != "" && VerbBox2 == "")//有1个动词
    {
        if (VerbBox1 == "给" || VerbBox1 == "送" || VerbBox1 == "送给" || VerbBox1 == "教")//双宾语句型的常见动词(标志词)
        {
            return "双宾语";//双宾语句型
        }
        else
        {
            return "主谓宾";//主谓宾句型
        }
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//有2个动词
    {
        return "宾语补足语";//宾语补足语句型
    }
    else
    {
        return "其它";
    }
}

//名词排序
void NounOrder()
{
    if (NounBox1 != "" && NounBox2 != "")//招到了2个名词,放在NounBox1和NounBox2
    {
        string temp = "";//临时变量
        if (dan.IndexOf(NounBox1) > dan.IndexOf(NounBox2))//如果NounBox1的名词在句子中的位置大于NounBox2的名词在句子中的位置
        {
            //交换位置,在句子中位置小的名词放前面,从而确保双宾语句型时,NounBox1放的是间接宾语,NounBox2放的是直接宾语,毕竟间接宾语在直接宾语前面
            temp = NounBox1;
            NounBox1 = NounBox2;
            NounBox2 = temp;
        }
        FindJianObject = NounBox1;
        FindZhiObject = NounBox2;
        //间接宾语和直接宾语的名词所有格,之后再做
    }
}

//名词结合成名词词组
void NounJoin()
{
    /*
    名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
    前面说了判断两个字符之间的内容,如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。
    示例:
    //截取两个指定字符之间的全部字符
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string res = "";//结果
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式
    if (res == "")
    {
        UnityEngine.Debug.Log("连续");
    }
    else
    {
        UnityEngine.Debug.Log("不连续");
    }
    */
    
    string res;
    //判断NounBox1和NounBox2的名词是否需要合并
    if (NounBox1 != "" && NounBox2 != "")
    {
        res = "";
        //判断NounBox1和NounBox2之间是否有内容,如果没内容(res为空),就说明NounBox1和NounBox2是连续的名词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(NounBox1) + NounBox1.Length, dan.IndexOf(NounBox2) - (dan.IndexOf(NounBox1) + NounBox1.Length));
        if (res == "")
        {
            NounBox1 = NounBox1 + NounBox2;//名词合并
            NounBox2 = "";//合并后,置空
            if (NounBox3 != "")
            {
                NounBox2 = NounBox3;//填补置空的值,否则NounBox1有值,NounBox2为空,NounBox3又有值,就间隔了
                NounBox3 = "";//合并后,置空
                if (NounBox4 != "")
                {
                    NounBox3 = NounBox4;
                    NounBox4 = "";//合并后,置空
                }
            }
        }
    }

    /*
    //判断NounBox2和NounBox3的名词是否需要合并
    if (NounBox2 != "" && NounBox3 != "")
    {
        res = "";
        //判断NounBox2和NounBox3之间是否有内容,如果没内容(res为空),就说明NounBox2和NounBox3是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox2) + NounBox2.Length, dan.IndexOf(NounBox3) - (dan.IndexOf(NounBox2) + NounBox2.Length));
        if (res == "")
        {
            NounBox2 = NounBox2 + NounBox3;//名词合并
            NounBox3 = "";//合并后,置空
            if (NounBox4 != "")
            {
                NounBox3 = NounBox4;//填补置空的值
                NounBox4 = "";//合并后,置空
            }
        }
    }

    //判断NounBox3和NounBox4的名词是否需要合并
    if (NounBox3 != "" && NounBox4 != "")
    {
        res = "";
        //判断NounBox3和NounBox4之间是否有内容,如果没内容(res为空),就说明NounBox3和NounBox4是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox3) + NounBox3.Length, dan.IndexOf(NounBox4) - (dan.IndexOf(NounBox3) + NounBox3.Length));
        if (res == "")
        {
            NounBox3 = NounBox3 + NounBox4;//名词合并
            NounBox4 = "";//合并后,置空
        }
    }
    */
}

//动词排序
void VerbOrder()
{
    /*
    如果不排序会怎样?句子中找到的第一个动词,可能不是谓语动词,而是宾语补足语动词,以宾语补足语动词分割句子,就错了。
    谓语动词和宾语补足语动词,先找到哪个,取决于这两个词,谁在动词表前面排序,而动词的排序是不可知的,或许按笔划排序,或者按首字母排序
    */
    string temp = "";//临时变量
    if (VerbBox1 != "" && VerbBox2 != "")//招到了个动词,放在VerbBox1和VerbBox2
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox2))//如果VerbBox1的动词在句子中的位置大于VerbBox2的动词在句子中的位置
        {
            //交换位置,在句子中位置小动词的放前面,从而确保VerbBox1放的是谓语动词,而宾语补足语动词放到VerbBox2
            temp = VerbBox1;
            VerbBox1 = VerbBox2;
            VerbBox2 = temp;
        }

    }
    if (VerbBox3 != "")
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox1;
            VerbBox1 = VerbBox3;
            VerbBox3 = temp;
        }
        if (dan.IndexOf(VerbBox2) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox2;
            VerbBox2 = VerbBox3;
            VerbBox3 = temp;
        }
    }
    FindVerb = VerbBox1;
}

//动词结合成动词词组
void VerbJoin()
{
    //动词合并:例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词
    string res;
    //判断VerbBox1和VerbBox2的动词是否需要合并
    if (VerbBox1 != "" && VerbBox2 != "")
    {
        res = "";
        //判断VerbBox1和VerbBox2之间是否有内容,如果没内容(res为空),就说明VerbBox1和VerbBox2是连续的动词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(VerbBox1) + VerbBox1.Length, dan.IndexOf(VerbBox2) - (dan.IndexOf(VerbBox1) + VerbBox1.Length));
        if (res == "")
        {
            VerbBox1 = VerbBox1 + VerbBox2;//名词合并
            FindVerb = VerbBox1;
            VerbBox2 = "";//合并后,置空
            if (VerbBox3 != "")
            {
                VerbBox2 = VerbBox3;//填补置空的值,否则VerbBox1有值,VerbBox2为空,VerbBox3又有值,就间隔了
                VerbBox3 = "";//合并后,置空
                if (VerbBox4 != "")
                {
                    VerbBox3 = VerbBox4;
                    VerbBox4 = "";//合并后,置空
                }
            }
        }
    }

}

//谓语动词的发生概率
void VerbRateJudge()
{
    /*
    动词前面是否有否定词,也很重要。
    例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
    谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
    还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
    因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
    但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
    那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
    这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 1, 1);
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 2, 1);
    */

    VerbRate = "肯定";//默认值:肯定
    string temp = "";//临时变量

    //先判断谓语动词左边的1个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不"))
    {
        VerbRate = "否定";
    }
    else if(temp.Contains("别"))
    {
        VerbRate = "否定";
    }

    //判断谓语动词左边的2个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不要"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不能"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("可能"))
    {
        VerbRate = "不确定";
    }
    else if (temp.Contains("或许"))
    {
        VerbRate = "不确定";
    }

    //判断谓语动词左边的3个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不可以"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不应该"))
    {
        VerbRate = "否定";
    }
}

//找形容词
string SearchAdj(string str)
{
    string jieguo = "不包含";//默认值是不包含
    int m = adj.Length;//形容词数组的长度,也就是有多少个形容词
    string temp  = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和形容词的包含关系
        就是用句子和形容词数组的形容词,一一比对,来判断是否包含形容词
        n的值从0逐渐增长到形容词数组的形容词数量值,这样数组也就经历了所有形容词
        */
        if (str.Contains(adj[n]))//包含
        {
            jieguo = "包含";
            temp = adj[n];
        }
    }

    if (jieguo == "包含")//找到了形容词
    {
        return temp;
    }
    else
    {
        return "";
    }
}

//找数词
string SearchNum(string str)
{
    /*
    找出数字(找出含有1、2、3这样的阿拉伯数字,而不是一、二、三这样的汉字型数字)。
    这种找数字方法用到了正则表达式。
    replace函数把不是数字的部分变为空无,这样就只剩下数字部分。
    */
    string res = "";
    res = Regex.Replace(str, @"[^0-9]+", "");
    return res;
}

//显示最终输出结果
void ShowResult()
{
    UnityEngine.Debug.Log("第" + dan_num + "句:" + danju[dan_num-1]);
    UnityEngine.Debug.Log("句型:" + SentenceType);

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("语态:" + yutai);
    }
    else if (SentenceType == "双宾语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("间接宾语:" + FindJianObject);
        UnityEngine.Debug.Log("直接宾语:" + FindZhiObject);
    }
    else if (SentenceType == "宾语补足语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("宾语补足语动词:" + FindBuVerb);
        UnityEngine.Debug.Log("宾语补足语名词:" + FindBuNoun);
    }
    else if (SentenceType == "只有性质状态")
    {
        UnityEngine.Debug.Log("只有性质状态:" + dan);
    }

    UnityEngine.Debug.Log("动词发生概率:" + VerbRate);

    //显示名词所有格
    if (SubjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("主语的名词所有格:" + SubjectSuoyouge);
    }
    if (ObjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语的名词所有格:" + ObjectSuoyouge);
    }
    /*
    if (JianSuoyouge != "")
    {
        UnityEngine.Debug.Log("间接宾语的名词所有格:" + JianSuoyouge);
    }
    if (ZhiSuoyouge != "")
    {
        UnityEngine.Debug.Log("直接宾语的名词所有格:" + ZhiSuoyouge);
    }
    if (BuSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语补足语的名词所有格:" + BuSuoyouge);
    }
    */

    //显示形容词
    if (SubjectAdj != "")
    {
        UnityEngine.Debug.Log("主语的形容词:" + SubjectAdj);
    }
    if (ObjectAdj != "")
    {
        UnityEngine.Debug.Log("宾语的形容词:" + ObjectAdj);
    }
    /*
    if (JianAdj != "")
    {
        UnityEngine.Debug.Log("间接宾语的形容词:" + JianAdj);
    }
    if (ZhiAdj != "")
    {
        UnityEngine.Debug.Log("直接宾语的形容词:" + ZhiAdj);
    }
    if (BuAdj != "")
    {
        UnityEngine.Debug.Log("宾语补足语的形容词:" + BuAdj);
    }
    */

    //显示数词
    if (SubjectNum != "")
    {
        UnityEngine.Debug.Log("主语的数词:" + SubjectNum);
    }
    if (ObjectNum != "")
    {
        UnityEngine.Debug.Log("宾语的数词:" + ObjectNum);
    }
    /*
    if (JianNum != "")
    {
        UnityEngine.Debug.Log("间接宾语的形容词:" + JianNum);
    }
    if (ZhiNum != "")
    {
        UnityEngine.Debug.Log("直接宾语的形容词:" + ZhiNum);
    }
    if (BuNum != "")
    {
        UnityEngine.Debug.Log("宾语补足语的形容词:" + BuNum);
    }
    */

    //tmpText.text = mes;

    //清空变量
    FindSubject = "";
    FindVerb = "";
    FindObject = "";
    FindBuVerb = "";
    FindBuNoun = "";
    FindJianObject = "";
    FindZhiObject = "";
    yutai = "";
    SubjectSuoyouge = "";
    ObjectSuoyouge = "";
    /*
    JianSuoyouge = "";
    ZhiSuoyouge = "";
    BuSuoyouge = "";
    */
}

}

第五章

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//Canvas框显示输入框和输出框所需
using TMPro;//Text Mesh Pro文字控件所需
using Mono.Data.Sqlite;//连接sqlite数据库所需

public class sqlitecon : MonoBehaviour
{
//输入和输出
public TMP_InputField inputField;//输入框对象(把层级面板上的输入框控件拖动到此框里)
string shuru = "";//输入框内容
//public TMP_Text tmpText;//输出框对象(把层级面板上的输出框控件拖动到此框里)
//string mes;//输出框内容
//词库
string[] noun = new string[7128];//名词数组,名词数量7128(数据库增加名词后,此处也要修改,以免造成溢出)
string[] verb = new string[5886];//动词数组,动词数量5886(数据库增加动词后,此处也要修改,以免造成溢出)
string[] adj = new string[1777];//形容词数组,形容词数量1777(数据库增加形容词后,此处也要修改,以免造成溢出)
int i = 0;//数组用的循环变量
//按标点符号分割句子
string dan = "";//按标点符号分割出的基本单句
string[] danju = new string[100];//单句的数组储存
int dan_num = 1;//第几个单句
//基本单句的语法结构
string FindSubject = "";//主语
string FindVerb = "";//谓语动词
string FindObject = "";//宾语
string FindBuVerb = "";//宾语补足语的动词
string FindBuNoun = "";//宾语补足语的名词
string FindJianObject = "";//间接宾语
string FindZhiObject = "";//直接宾语
//名词所有格(例如张三的猫,张三就是名词所有格,“的”字就不写了)
string SubjectSuoyouge = "";//主语的名词所有格
string ObjectSuoyouge = "";//宾语的名词所有格
//string JianSuoyouge = "";//间接宾语的名词所有格
//string ZhiSuoyouge = "";//直接宾语的名词所有格
//string BuSuoyouge = "";//宾语补足语的名词所有格
string TempSuoyouge = "";//临时存放名词所有格
//形容词
string SubjectAdj = "";//主语的形容词
string ObjectAdj = "";//宾语的形容词
//string JianAdj = "";//间接宾语的形容词
//string ZhiAdj = "";//直接宾语的形容词
//string BuAdj = "";//宾语补足语的形容词
//数词
string SubjectNum = "";//主语的数词
string ObjectNum = "";//宾语的数词
//string JianNum = "";//间接宾语的数词
//string ZhiNum = "";//直接宾语的数词
//string BuNum = "";//宾语补足语的数词
//语法结构的相关描述
string SentenceType = "";//句型
string yutai = "";//语态:主动语态还是被动语态
string VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
//名词槽(名词之间相互覆盖时用)
string NounBox1 = "";//名词槽1
string NounBox2 = "";//名词槽2
string NounBox3 = "";//名词槽3
string NounBox4 = "";//名词槽4
//动词槽(动词之间相互覆盖时用)
string VerbBox1 = "";//动词槽1
string VerbBox2 = "";//动词槽2
string VerbBox3 = "";//动词槽3
string VerbBox4 = "";//动词槽4
//数词和时间
string FindNum = "";//要找的数词的数字
string NumDanwei = "";//数词单位
string FindTime_year = "";//要找的时间:年
string FindTime_month = "";//要找的时间:月
string FindTime_day = "";//要找的时间:日
string FindTime_hour = "";//要找的时间:小时
string FindTime_minute = "";//要找的时间:分钟
string FindTime2 = "";//要找的时间(文字形式,例如下午、星期一)
string num_type = "";//数字类型:阿拉伯数字(例如1、2、3)还是汉字型数字(例如一、二、三)

// Start is called before the first frame update
void Start()
{
    ciku();//填充词库
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应(按回车键发送)
}

// Update is called once per frame
void Update()
{

}

//填充词库(数据库的词库填充到数组中)
void ciku()
{
    //生成游戏后,需要把sqlite数据库复制到生成的游戏的文件夹里,那个文件夹自动生成的这个数据库是0kb,无效的,需要重新复制过去
    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    //填充形容词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM adj";//sql指令
    //第二步:执行指令
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        adj[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示形容词数量

    dbConnection.Close();//关闭数据库连接
}

//输入完成后,按回车键发送,便开始执行此函数
void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的内容
    SplitSay();//按标点符号,分割输入内容
}

//按标点符号,分割输入内容,分割成基本单句
void SplitSay()
{
    /*
    输入的内容可能是一大段内容,需要分割成一个个基本单句,从而逐一处理。
    基本单句就是主语-谓语-宾语,或主语-谓语-间接宾语-直接宾语,或主语-谓语-宾语-宾语补足语,这类语法上的基本单句。
    那就需要按逗号分割句子,按句号分割句子,才能拆分成一个个这样的基本单句。

    按逗号分割句子:
    string str = "早晨,中午,下午";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符,分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    按逗号和句号分割句子:
    string str = "早晨,中午。下午,傍晚";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        string word2 = "。";
        string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
        foreach (string part2 in shuzu2)
        {
            UnityEngine.Debug.Log(part2);
        }
    }

    计算标点符号的数量:
    string str = "早晨,中午。下午,傍晚";
    string temp = "";

    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = str.Length;//句子长度

    temp = str.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量

    temp = str.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    以上注释掉的内容,只是解释说明,下面才是运行的程序:
    */

    //计算标点符号的数量
    string temp = "";
    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = shuru.Length;//句子长度
    //计算逗号的数量
    temp = shuru.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量
    //计算句号的数量
    temp = shuru.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    //按标点符号分割句子
    if (dou > 0 || ju > 0)//逗号大于0或句号大于0,就是输入的内容有标点符号
    {
        string word = ",";//分割符:中文的逗号
        string[] shuzu = shuru.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
        foreach (string part in shuzu)//逐个处理
        {
            string word2 = "。";//分割符:中文的句号
            string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
            foreach (string part2 in shuzu2)//逐个处理
            {
                dan = part2;//基本单句已经分割出来了,在part2里,并赋值给dan(基本单句)
                danju[dan_num - 1] = part2;//数组从0开始计算,而danju从1开始计算,所以换算上要减1
                ClearData();//清除上次的变量数据
                //UnityEngine.Debug.Log("单句:" + dan);
                SearchVerb(dan);//找谓语动词(这是单句处理的第一步)
                dan = "";
                dan_num++;
            }
        }
    }
    else//输入的内容,没有标点符号
    {
        if (shuru != "")//有输入的内容
        {
            dan = shuru;//输入的内容就是一个基本单句
            danju[0] = shuru;
            SearchVerb(dan);//找谓语动词
            dan = "";
        }
    }
}

//清除上次循环(基本单句处理)的变量数据
void ClearData()
{
    FindSubject = "";//主语
    FindVerb = "";//谓语动词
    FindObject = "";//宾语
    FindBuVerb = "";//宾语补足语的动词
    FindBuNoun = "";//宾语补足语的名词
    FindJianObject = "";//间接宾语
    FindZhiObject = "";//直接宾语
    SubjectSuoyouge = "";//主语的名词所有格
    ObjectSuoyouge = "";//宾语的名词所有格
    TempSuoyouge = "";//临时存放名词所有格
    SubjectAdj = "";//主语的形容词
    ObjectAdj = "";//宾语的形容词
    SubjectNum = "";//主语的数词
    ObjectNum = "";//宾语的数词
    SentenceType = "";//句型
    yutai = "";//语态:主动语态还是被动语态
    VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
    NounBox1 = "";//名词槽1
    NounBox2 = "";//名词槽2
    NounBox3 = "";//名词槽3
    NounBox4 = "";//名词槽4
    VerbBox1 = "";//动词槽1
    VerbBox2 = "";//动词槽2
    VerbBox3 = "";//动词槽3
    VerbBox4 = "";//动词槽4
    FindNum = "";
    NumDanwei = "";
    num_type = "";
    i = 0;
}

//找谓语动词
void SearchVerb(string str)
{
    string jieguo = "不包含";//默认值是不包含动词
    int m = verb.Length;//动词数组的长度,也就是有多少个动词

    VerbBox1 = "";
    VerbBox2 = "";
    VerbBox3 = "";
    VerbBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (str.Contains(verb[n]))//包含动词
        {
            if (VerbJudge(str, verb[n]) == true)//是动词,不是名词
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
                VerbCover(str, verb[n]);//把动词放入动词槽里,看看有几个动词
                VerbOrder();//动词排序
                VerbJoin();//动词结合
            }
        }
    }

    if (jieguo == "包含")//包含动词
    {
        VerbRateJudge();//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
        SentenceType = SentenceJudge();//判断句型(仅从动词情况来判断句型,还不是完全清楚的判断,之后还需进一步判断)
        SplitSentence();//以谓语动词为分割符,来分割句子
    }
}

//以谓语动词为分割符,来分割句子
void SplitSentence()
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string word = "嘲笑";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词语的起始位置
    int LastIndex = 0;//指定词语最后一个字符在全句中的位置
    int jie = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    //计算指定字符在全句中的位置
    index = str.IndexOf(word) + 1;//默认从0计算,例如第2个字符,显示为1,而不是2。为了调整为1开始计算,所以加1
    //计算指定词语最后一个字符在全句中的位置
    LastIndex = str.IndexOf(word) + word.Length;

    //截取第3个字符右边的1个字符
    Substring(开始位置, 向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符

    //截取指定字符右边的全部字符
    jie = chang - LastIndex;//截取长度 = 全句长度 - 指定词语最后一个字符的位置长度
    res = str.Substring(LastIndex, jie);
    res = str.Substring(str.IndexOf(word) + word.Length, str.Length - (str.IndexOf(word) + word.Length));//展开形式

    //截取指定字符左边的全部字符
    res = str.Substring(0, index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0, str.IndexOf(word));//变化形式

    //截取两个指定字符之间的全部字符
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    以上注释掉的内容,只是解释原理,下面是运行的程序:
    */

    string LeftPart = "";//谓语动词的左边句
    string RightPart = "";//谓语动词的右边句

    //也可能找到一个动词(主谓宾句型),也可能找到两个动词(宾语补足语句型)
    if (VerbBox1 != "" && VerbBox2 == "")//只找到1个动词,那就是谓语动词
    {
        FindVerb = VerbBox1;
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//找到2个动词
    {
        FindVerb = VerbBox1;//位次在前面的动词是谓语动词
        FindBuVerb = VerbBox2;//位次在后面的动词是宾语补足语动词
    }

    //谓语动词左边句(LeftPart)和谓语动词右边句(RightPart)是一个重要的转折,为以后的句子处理奠定了基础
    LeftPart = dan.Substring(0, dan.IndexOf(FindVerb));
    RightPart = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.Length - (dan.IndexOf(FindVerb) + FindVerb.Length));

    /*
    例如句子(dan)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);//谓语动词
    UnityEngine.Debug.Log(LeftPart);//谓语动词的左边句
    UnityEngine.Debug.Log(RightPart);//谓语动词的右边句
    */

    /*
    省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
    被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
    被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
    程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
    但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
    简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
    如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
    那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。
    */
    yutai = "主动";//默认主动语态
    if (SentenceType == "主谓宾" && dan.Contains("被"))//语句中包含“被”字
    {
        if (dan.Contains("被子") == false && dan.Contains("被褥") == false)//语句中包含“被”字,但不是“被子”这个名词,才能指被动语态的“被”字
        {
            yutai = "被动";//被动语态
        }
        else
        {
            yutai = "主动";//主动语态
        }
    }
    else//语句中没有包含“被”字
    {
        yutai = "主动";//主动语态
    }

    //对谓语动词左边句(LeftPart)的处理
    if (LeftPart != "")//谓语动词左边句有内容
    {
        if (yutai == "主动")//主动语态
        {
            //找名词(主语)和名词所有格
            FindSubject = SearchNoun(LeftPart);//在谓语动词左边句找名词(主语)
            if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
            {
                SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                TempSuoyouge = "";//置空
            }
            //找形容词(主语的形容词)
            SubjectAdj = SearchAdj(LeftPart);
            //找数词
            FindNum = "";
            NumDanwei = "";
            num_type = "";
            SearchNum(LeftPart);
            SubjectNum = FindNum + NumDanwei;
            //找时间
            SearchTime1(LeftPart);//找时间:文字形式,例如今天、星期一
            SearchTime2(LeftPart);//找时间:年月日时分
        }
        else if (yutai == "被动")//被动语态
        {
            string bei = "被";
            string BeiLeft = "";
            string BeiRight = "";

            //被字左边句
            BeiLeft = LeftPart.Substring(0, LeftPart.IndexOf(bei));
            if (BeiLeft != "")
            {
                FindObject = SearchNoun(BeiLeft);//被字左边句的名词是宾语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(BeiLeft);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(BeiLeft);
                ObjectNum = FindNum + NumDanwei;
            }

            //被字右边句
            BeiRight = LeftPart.Substring(LeftPart.IndexOf(bei) + bei.Length, LeftPart.Length - (LeftPart.IndexOf(bei) + bei.Length));
            
            if (BeiRight != "")
            {
                FindSubject = SearchNoun(BeiRight);//被字右边句的名词是主语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(主语的形容词)
                SubjectAdj = SearchAdj(BeiRight);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(BeiRight);
                SubjectNum = FindNum + NumDanwei;
            }
            //如果没有主语,就填补“事物”这个词作为主语,毕竟被动语态经常没有主语
            if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
            {
                FindSubject = "事物";
            }
        }
    }

    //如果省略主语,则填补省略的主语
    if (yutai == "主动")
    {
        if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
        {
            FindSubject = "你";//默认填补“你”字做主语
        }
    }

    //对谓语动词右边句(RightPart)的处理
    if (SentenceType == "双宾语")//双宾语句型
    {
        FindObject = SearchNoun(RightPart);//找名词

        //谓语动词右边句里,没有第二个宾语名词,那就不是双宾语
        //例如虽然有双宾语句的标志动词“教”字,但他教我数学,是双宾语句,而他教书,是主谓宾句型
        if (NounBox2 == "")
        {
            SentenceType = "主谓宾";
        }
        else
        {
            ShowResult();//显示最终输出结果
        }
    }

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        if (RightPart != "")
        {
            if (yutai == "主动")
            {
                //找名词和名词所有格
                FindObject = SearchNoun(RightPart);//在谓语动词右边句找名词(宾语)
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }

                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(RightPart);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(RightPart);
                ObjectNum = FindNum + NumDanwei;
            }
        }

        ShowResult();//显示最终输出结果
    }

    if (SentenceType == "宾语补足语")//宾语补足语句型
    {
        //谓语动词到宾语补足语动词之间的部分里的名词,是宾语名词
        string temp = "";
        //截取谓语动词FindVerb和宾语补足语动词FindBuVerb之间的部分
        temp = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.IndexOf(FindBuVerb) - (dan.IndexOf(FindVerb) + FindVerb.Length));
        FindObject = SearchNoun(temp);//找名词
        if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
        {
            ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
            TempSuoyouge = "";//置空
        }
        //宾语补足语右边句的名词,是宾语补足语名词,而不是宾语名词
        int WordLastChar = dan.IndexOf(FindBuVerb) + FindBuVerb.Length;//宾语补足语动词最后一个字符的位置
        if (WordLastChar < dan.Length)//宾语补足语动词最后一个字符的位置没有到全句末尾,就是说宾语补足语动词后面还有内容,那就是宾语补足语名词
        {
            //截取宾语补足语动词右边的内容
            FindBuNoun = dan.Substring(dan.IndexOf(FindBuVerb) + FindBuVerb.Length, dan.Length - (dan.IndexOf(FindBuVerb) + FindBuVerb.Length));
            //以后再写找宾语补足语名词的名词所有格
        }

        ShowResult();//显示最终输出结果
    }

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

//找名词(也包括找名词所有格)
string SearchNoun(string PartSentence)
{
    string jieguo = "不包含";//默认值是不包含
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    NounBox1 = "";
    NounBox2 = "";
    NounBox3 = "";
    NounBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//包含
        {
            jieguo = "包含";
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字,才算是名词,否则是名词所有格
            {
                NounCover(noun[n]);
            }
            else//名词右边的第一个字是“的”字,就意味着是名词所有格
            {
                TempSuoyouge = noun[n];//找到的名词所有格
            }
        }
    }

    if (jieguo == "包含")//找到了名词
    {
        NounOrder();//名词排序
        //名词要先排序,才能合并名词,否则“足球”和“学校”的顺序如果变成“学校”和“足球”,那就合并成“学校足球”这个词了,而不是“足球学校”

        //如果双宾语句型进行名词合并,就可能会把间接宾语名词和直接宾语名词合并到一起,成为一个名词,就不对了
        if (SentenceType != "双宾语")//不是双宾语句型
        {
            NounJoin();//名词合并,例如把“足球”和“学校”合并成“足球学校”这一个名词
        }
        else if (SentenceType == "双宾语")//是双宾语句型
        {
            //但是如果现在处理的是双宾语结构的谓语动词左边句,也就是处理主语,还是可以名词合并的
            if (dan.IndexOf(NounBox1) < dan.IndexOf(FindVerb))
            {
                NounJoin();//名词合并
            }
        }

        return NounBox1;
    }
    else
    {
        return "";
    }
}

//名词之间的覆盖
void NounCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(NounBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (NounBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        NounBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (NounBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(NounBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (NounBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(NounBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (NounBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        NounBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (NounBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(NounBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (NounBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(NounBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (NounBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        NounBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (NounBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(NounBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (NounBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(NounBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (NounBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        NounBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (NounBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(NounBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (NounBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(NounBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    /*
    “足球”这个词,会找到三个名词:足、球、足球。
    先找到第一个词:足,放入NounBox1。
    再找到第二个词:球,放入NounBox2。
    再找到第三个词:足球,会覆盖NounBox1的“足”字,但却无法覆盖NounBox2的球字。
    因此程序做一些改进。

    但如果幸运的:
    先找到第一个词:足球,放入NounBox1。
    再找到第二个词:足,被NounBox1“足球”这个词吸收,不会进入到NounBox2。
    再找到第三个词:球,被NounBox1“足球”这个词吸收,也不会进入到NounBox2。
    那么就不用执行下面这段程序了。
    先找到那个词是不确定的,词库词语可能按笔画排序,也可能按首字母排序,就不知道先找到那个词了。

    如果输入的是“皮球”这个词,而词库里没有“皮球”这个词,但有“皮”字和“球”字这两个词。
    那么,NounBox1是“皮”字,NounBox2是“球”字,或NounBox1是“球”字,NounBox2是“皮”字,没有覆盖和吸收。
    */
    if (NounBox1.Contains(NounBox2))//NounBox1包含了NounBox2,例如“足球”包含“球”字
    {
        NounBox2 = "";
        if (NounBox3 != "")
        {
            NounBox2 = NounBox3;
            NounBox3 = "";
        }
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox2.Contains(NounBox3))//NounBox2包含了NounBox3
    {
        NounBox3 = "";
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox3.Contains(NounBox4))//NounBox3包含了NounBox4
    {
        NounBox4 = "";
    }
}

//动词之间的覆盖
void VerbCover(string str,string FindWord)
{
    if (VerbBox1 == "" && FindWord != "")//动词槽还是空的,说明这是找到的第一个词
    {
        VerbBox1 = FindWord;//找到的第1个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽2了
    }
    else if (VerbBox1 != "" && FindWord != "")//动词槽1已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox1))//覆盖:例如找到的词(FindWord)是敲打,动词槽1(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“敲打”覆盖“打”
            FindWord = "";//置空,免得填到动词槽2了
        }
        else if (VerbBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽1(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,不要这个词了,免得填到动词槽2了
        }
    }

    if (VerbBox2 == "" && FindWord != "")//动词槽2是空的,FindWord经过动词槽1,没有覆盖或吸收,说明FindWord和动词槽1的词无关,例如FindWord是喜欢
    {
        VerbBox2 = FindWord;//找到的第2个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽3了
    }
    else if (VerbBox2 != "" && FindWord != "")//动词槽2已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox2))//覆盖:例如找到的词(FindWord)是敲打,动词槽2(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (VerbBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽2(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (VerbBox3 == "" && FindWord != "")//动词槽3是空的,FindWord经过动词槽1和2,没有覆盖或吸收,说明FindWord和动词槽1、2的词无关,例如FindWord是喜欢
    {
        VerbBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (VerbBox3 != "" && FindWord != "")//动词槽3已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox3))//覆盖:例如找到的词(FindWord)是敲打,动词槽3(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (VerbBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽3(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (VerbBox4 == "" && FindWord != "")//动词槽4是空的,FindWord经过动词槽1、2、3,没有覆盖或吸收,说明FindWord和动词槽1、2、3的词无关,例如FindWord是喜欢
    {
        VerbBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (VerbBox4 != "" && FindWord != "")//动词槽4已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox4))//覆盖:例如找到的词(FindWord)是敲打,动词槽4(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (VerbBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽4(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空
        }
    }

    /*
    “敲打”这个词,会找到三个动词:敲、打、敲打
    先找到第一个词:敲,放入VerbBox1
    再找到第二个词:打,放入VerbBox2
    再找到第三个词:敲打,会覆盖VerbBox1的“敲”字,但却无法覆盖VerbBox2的“打”字
    因此程序做一些改进。 
    */
    if (VerbBox1.Contains(VerbBox2))//VerbBox1包含了VerbBox2
    {
        VerbBox2 = "";
        if (VerbBox3 != "")
        {
            VerbBox2 = VerbBox3;
            VerbBox3 = "";
        }
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox2.Contains(VerbBox3))//VerbBox2包含了VerbBox3
    {
        VerbBox3 = "";
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox3.Contains(VerbBox4))//VerbBox3包含了VerbBox4
    {
        VerbBox4 = "";
    }
}

//名词后面是否包含“的”字
bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上注释掉的内容只是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }

}

//判断一个字是动词还是名词
bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   吹     |   l1    |      电      |
    +----------+---------+--------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上注释掉的内容,只是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

//判断句型
string SentenceJudge()
{
    /*
    基本单句有六种句型:
    只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
    主语(动作执行者)-谓语(动作):张三摔倒。
    主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
    主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
    双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
    宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
    前面只说了主谓宾句型,还要处理其它句型。

    双宾语句型:
    双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
    但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
    双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
    那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
    还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
    仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
    名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

    宾语补足语句型:
    和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
    因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
    但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
    既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
    动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
    宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

    双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

    在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。
    */

    if (VerbBox1 == "")//没有动词
    {
        return "只有性质状态";//只有性质状态的句型
    }
    else if (VerbBox1 != "" && VerbBox2 == "")//有1个动词
    {
        if (VerbBox1 == "给" || VerbBox1 == "送" || VerbBox1 == "送给" || VerbBox1 == "教")//双宾语句型的常见动词(标志词)
        {
            return "双宾语";//双宾语句型
        }
        else
        {
            return "主谓宾";//主谓宾句型
        }
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//有2个动词
    {
        return "宾语补足语";//宾语补足语句型
    }
    else
    {
        return "其它";
    }
}

//名词排序
void NounOrder()
{
    if (NounBox1 != "" && NounBox2 != "")//招到了2个名词,放在NounBox1和NounBox2
    {
        string temp = "";//临时变量
        if (dan.IndexOf(NounBox1) > dan.IndexOf(NounBox2))//如果NounBox1的名词在句子中的位置大于NounBox2的名词在句子中的位置
        {
            //交换位置,在句子中位置小的名词放前面,从而确保双宾语句型时,NounBox1放的是间接宾语,NounBox2放的是直接宾语,毕竟间接宾语在直接宾语前面
            temp = NounBox1;
            NounBox1 = NounBox2;
            NounBox2 = temp;
        }
        FindJianObject = NounBox1;
        FindZhiObject = NounBox2;
        //间接宾语和直接宾语的名词所有格,之后再做
    }
}

//名词结合成名词词组
void NounJoin()
{
    /*
    名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
    前面说了判断两个字符之间的内容,如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。
    示例:
    //截取两个指定字符之间的全部字符
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string res = "";//结果
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式
    if (res == "")
    {
        UnityEngine.Debug.Log("连续");
    }
    else
    {
        UnityEngine.Debug.Log("不连续");
    }
    */
    
    string res;
    //判断NounBox1和NounBox2的名词是否需要合并
    if (NounBox1 != "" && NounBox2 != "")
    {
        res = "";
        //判断NounBox1和NounBox2之间是否有内容,如果没内容(res为空),就说明NounBox1和NounBox2是连续的名词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(NounBox1) + NounBox1.Length, dan.IndexOf(NounBox2) - (dan.IndexOf(NounBox1) + NounBox1.Length));
        if (res == "")
        {
            NounBox1 = NounBox1 + NounBox2;//名词合并
            NounBox2 = "";//合并后,置空
            if (NounBox3 != "")
            {
                NounBox2 = NounBox3;//填补置空的值,否则NounBox1有值,NounBox2为空,NounBox3又有值,就间隔了
                NounBox3 = "";//合并后,置空
                if (NounBox4 != "")
                {
                    NounBox3 = NounBox4;
                    NounBox4 = "";//合并后,置空
                }
            }
        }
    }

    /*
    //判断NounBox2和NounBox3的名词是否需要合并
    if (NounBox2 != "" && NounBox3 != "")
    {
        res = "";
        //判断NounBox2和NounBox3之间是否有内容,如果没内容(res为空),就说明NounBox2和NounBox3是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox2) + NounBox2.Length, dan.IndexOf(NounBox3) - (dan.IndexOf(NounBox2) + NounBox2.Length));
        if (res == "")
        {
            NounBox2 = NounBox2 + NounBox3;//名词合并
            NounBox3 = "";//合并后,置空
            if (NounBox4 != "")
            {
                NounBox3 = NounBox4;//填补置空的值
                NounBox4 = "";//合并后,置空
            }
        }
    }

    //判断NounBox3和NounBox4的名词是否需要合并
    if (NounBox3 != "" && NounBox4 != "")
    {
        res = "";
        //判断NounBox3和NounBox4之间是否有内容,如果没内容(res为空),就说明NounBox3和NounBox4是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox3) + NounBox3.Length, dan.IndexOf(NounBox4) - (dan.IndexOf(NounBox3) + NounBox3.Length));
        if (res == "")
        {
            NounBox3 = NounBox3 + NounBox4;//名词合并
            NounBox4 = "";//合并后,置空
        }
    }
    */
}

//动词排序
void VerbOrder()
{
    /*
    如果不排序会怎样?句子中找到的第一个动词,可能不是谓语动词,而是宾语补足语动词,以宾语补足语动词分割句子,就错了。
    谓语动词和宾语补足语动词,先找到哪个,取决于这两个词,谁在动词表前面排序,而动词的排序是不可知的,或许按笔划排序,或者按首字母排序
    */
    string temp = "";//临时变量
    if (VerbBox1 != "" && VerbBox2 != "")//招到了个动词,放在VerbBox1和VerbBox2
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox2))//如果VerbBox1的动词在句子中的位置大于VerbBox2的动词在句子中的位置
        {
            //交换位置,在句子中位置小动词的放前面,从而确保VerbBox1放的是谓语动词,而宾语补足语动词放到VerbBox2
            temp = VerbBox1;
            VerbBox1 = VerbBox2;
            VerbBox2 = temp;
        }

    }
    if (VerbBox3 != "")
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox1;
            VerbBox1 = VerbBox3;
            VerbBox3 = temp;
        }
        if (dan.IndexOf(VerbBox2) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox2;
            VerbBox2 = VerbBox3;
            VerbBox3 = temp;
        }
    }
    FindVerb = VerbBox1;
}

//动词结合成动词词组
void VerbJoin()
{
    //动词合并:例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词
    string res;
    //判断VerbBox1和VerbBox2的动词是否需要合并
    if (VerbBox1 != "" && VerbBox2 != "")
    {
        res = "";
        //判断VerbBox1和VerbBox2之间是否有内容,如果没内容(res为空),就说明VerbBox1和VerbBox2是连续的动词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(VerbBox1) + VerbBox1.Length, dan.IndexOf(VerbBox2) - (dan.IndexOf(VerbBox1) + VerbBox1.Length));
        if (res == "")
        {
            VerbBox1 = VerbBox1 + VerbBox2;//名词合并
            FindVerb = VerbBox1;
            VerbBox2 = "";//合并后,置空
            if (VerbBox3 != "")
            {
                VerbBox2 = VerbBox3;//填补置空的值,否则VerbBox1有值,VerbBox2为空,VerbBox3又有值,就间隔了
                VerbBox3 = "";//合并后,置空
                if (VerbBox4 != "")
                {
                    VerbBox3 = VerbBox4;
                    VerbBox4 = "";//合并后,置空
                }
            }
        }
    }

}

//谓语动词的发生概率
void VerbRateJudge()
{
    /*
    动词前面是否有否定词,也很重要。
    例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
    谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
    还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
    因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
    但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
    那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
    这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 1, 1);
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 2, 1);
    */

    VerbRate = "肯定";//默认值:肯定
    string temp = "";//临时变量

    //先判断谓语动词左边的1个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不"))
    {
        VerbRate = "否定";
    }
    else if(temp.Contains("别"))
    {
        VerbRate = "否定";
    }

    //判断谓语动词左边的2个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不要"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不能"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("可能"))
    {
        VerbRate = "不确定";
    }
    else if (temp.Contains("或许"))
    {
        VerbRate = "不确定";
    }

    //判断谓语动词左边的3个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不可以"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不应该"))
    {
        VerbRate = "否定";
    }
}

//找形容词
string SearchAdj(string str)
{
    string jieguo = "不包含";//默认值是不包含
    int m = adj.Length;//形容词数组的长度,也就是有多少个形容词
    string temp  = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和形容词的包含关系
        就是用句子和形容词数组的形容词,一一比对,来判断是否包含形容词
        n的值从0逐渐增长到形容词数组的形容词数量值,这样数组也就经历了所有形容词
        */
        if (str.Contains(adj[n]))//包含
        {
            jieguo = "包含";
            temp = adj[n];
        }
    }

    if (jieguo == "包含")//找到了形容词
    {
        return temp;
    }
    else
    {
        return "";
    }
}

//找数词
void SearchNum(string str)
{
    //先确定数词单位
    int StrLength = str.Length;//全句长度
    string temp = "";
    string NumDanwei_type = "";//数字单位类型

    string[] shuzu_danwei_mignci = new string[] { "个", "名", "位", "只", "头", "匹", "条", "棵", "朵", "片", "根", "座", "栋", "台", "部", "本", "块", "件", "盏", "把", "所", "辆", "艘", "架", "扇" };
    string[] shuzu_danwei_jiliang = new string[] { "米", "厘米", "毫米", "分米", "公里", "里", "微米", "纳米", "克", "斤", "公斤", "吨", "毫克", "升" };

    //字符串从右向左,每次读取一个字符进行处理
    for (int n = StrLength; n > 0; n--)
    {
        temp = str.Substring(n - 1, 1);//每次截取的一个字符,例如“年”字

        if (NumDanwei_type == "")
        {
            //名词单位数组
            foreach (string m in shuzu_danwei_mignci)//判断这个截取的字符是否在名词数组中
            {
                if (temp == m)//截取的字符属于名词数组(shuzu_danwei_mignci)中的字符,例如“个”字属于名词数组
                {
                    NumDanwei = m;
                    NumDanwei_type = "名词单位";
                    SearchNum2(str, NumDanwei, NumDanwei_type);

                    if (num_type == "汉字型数字")
                    {
                        FindNum = SearchNum3(FindNum);
                    }
                    break;
                }
            }
        }

        if (NumDanwei_type == "")
        {
            //计量数组
            foreach (string m in shuzu_danwei_jiliang)//判断这个截取的字符是否在计量数组中
            {
                if (temp == m)//截取的字符属于计量数组(shuzu_danwei_jiliang)中的字符,例如“米”字属于计量数组
                {
                    NumDanwei = m;
                    if (str.Contains("厘"))
                    {
                        NumDanwei = "厘" + NumDanwei;
                    }
                    else if (str.Contains("毫"))
                    {
                        NumDanwei = "毫" + NumDanwei;
                    }
                    else if (str.Contains("公"))
                    {
                        NumDanwei = "公" + NumDanwei;
                    }
                    NumDanwei_type = "计量单位";
                    SearchNum2(str, NumDanwei, NumDanwei_type);
                    if (num_type == "汉字型数字")
                    {
                        FindNum = SearchNum3(FindNum);
                    }
                    break;
                }
            }
        }
    }

    /*
    找数字的其它方法:正则表达式。
    需要using System.Text.RegularExpressions;//正则表达式找出数字所需
    replace函数把不是数字的部分变为空无,这样就只剩下数字部分。
    string res = "";
    res = Regex.Replace(str, @"[^0-9]+", "");
    return res;
    */
}

void SearchNum2(string str, string temp, string NumDanwei_type)
{
    //找数字
    string[] shuzu_num = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
    string[] shuzu_num_cn = new string[] { "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "零", "十", "百", "千", "万" };

    //数量单位字符左边的字符串
    string WordLeft = str.Substring(0, str.IndexOf(temp));//例如“有6米”的“有6”

    //找阿拉伯数字,例如1、2、3这类数字
    //逐一处理该字符左边的每个字符
    int WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
    string temp2 = "";
    //从右向左,逐字截取
    for (int j = WordleftLength; j > 0; j--)
    {
        temp2 = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
                                             //从右到左,遇到不是数字的时候,就退出循环
        if (temp2 != "1" && temp2 != "2" && temp2 != "3" && temp2 != "4" && temp2 != "5" && temp2 != "6" && temp2 != "7" && temp2 != "8" && temp2 != "9" && temp2 != "0")
        {
            break;
        }
        foreach (string m2 in shuzu_num)//判断这个截取的字符是否在数字数组中
        {
            if (temp2 == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
            {
                if (NumDanwei_type == "名词单位" || NumDanwei_type == "计量单位")
                {
                    //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                    if (FindNum == "")
                    {
                        FindNum = temp2;
                    }
                    else
                    {
                        FindNum = temp2 + FindNum;
                    }
                    num_type = "阿拉伯数字";
                }
            }
        }
    }

    if (NumDanwei_type == "名词单位" || NumDanwei_type == "计量单位")
    {
        if (FindNum == "")//没有找到阿拉伯数字
        {
            //找汉字型数字,例如一、二、三
            WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
            temp2 = "";
            //从右向左,逐字截取
            for (int j = WordleftLength; j > 0; j--)
            {
                temp2 = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
                foreach (string m2 in shuzu_num_cn)//判断这个截取的字符是否在数字数组中
                {
                    if (temp2 == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
                    {
                        //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                        if (FindNum == "")
                        {
                            FindNum = temp2;
                        }
                        else
                        {
                            FindNum = temp2 + FindNum;
                        }
                        num_type = "汉字型数字";
                    }
                }
            }
        }
    }
}

string SearchNum3(string find_num)
{
    //汉字型数字转化为阿拉伯数字,例如“二十”转化为“20”
    //这个转化有时候不准确
    int old = 1;
    int result = 0;
    string temp = "";
    int temp_num = 0;

    //old(上一位数字)需要初始化为1,不能初始化为0,也不能不赋值
    //因为如果数字开始(从左到右)第一个字符就是翻倍数(例如十),那么翻倍的上一位数(old)不能默认0或NULL
    //如果翻倍数没有上一位数,拿默认1当上一位数(old初始化为1),翻倍数乘以1,就等于翻倍数翻倍自身,这样才正确

    for (int n = 1; n <= find_num.Length; n++)
    {
        temp = find_num.Substring(n - 1, 1);//每次截取的一个字符
        switch (temp)
        {
            case "一":
                temp_num = 1;
                break;
            case "二":
                temp_num = 2;
                break;
            case "两":
                temp_num = 2;
                break;
            case "三":
                temp_num = 3;
                break;
            case "四":
                temp_num = 4;
                break;
            case "五":
                temp_num = 5;
                break;
            case "六":
                temp_num = 6;
                break;
            case "七":
                temp_num = 7;
                break;
            case "八":
                temp_num = 8;
                break;
            case "九":
                temp_num = 9;
                break;
            case "零":
                temp_num = 0;
                break;
            case "十":
                temp_num = 10;
                break;
            case "百":
                temp_num = 100;
                break;
            case "千":
                temp_num = 1000;
                break;
            case "万":
                temp_num = 10000;
                break;
            default:
                break;
        }

        if (temp_num != 10 && temp_num != 100 && temp_num != 1000 && temp_num != 10000)//不是翻倍字符(十、百、千、万),而是0到9的数字
        {
            old = temp_num;//把数字存起来,下一次循环时,被下一位翻倍数所翻倍
            if (n == find_num.Length)//当i的长度等于总数字的长度,也就是到了最后一位数(个位数),不用翻倍了
            {
                result = result + temp_num;//个位数不用翻倍,直接加
            }
        }
        else//不是0到9的数字字符,而是翻倍字符,就要翻倍
        {
            //翻倍对象是上一位数字,就是old里存的数字。因为这次循环走else路线,所以temp_num没有赋值给old,因此old里还是上一位的数字
            result = result + (old * temp_num);//此时的temp_num是翻倍单位(十、百、千、万),不是0到9的数字,翻倍上一位数字(old)
        }
    }

    if (result != 0)
    {
        find_num = result.ToString();
        return find_num;
    }
    else
    {
        return "";
    }
}

//找时间(文字形式)
void SearchTime1(string str)
{
    string[] shuzu_danwei_time1 = new string[] { "今天", "明天", "后天", "昨天", "前天", "这个月", "下个月", "上个月", "今年", "明年", "去年" };
    string[] shuzu_danwei_time2 = new string[] { "早晨", "上午", "中午", "下午", "傍晚", "晚上", "傍晚", "夜晚", "半夜", "黎明", "黄昏", "清晨" };
    string[] shuzu_danwei_time3 = new string[] { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日", "礼拜一", "礼拜二", "礼拜三", "礼拜四", "礼拜五", "礼拜六", "礼拜天" };
    string[] shuzu_danwei_time4 = new string[] { "春天", "夏天", "秋天", "冬天", "春季", "夏季", "秋季", "冬季" };
    string[] shuzu_danwei_time5 = new string[] { "元旦", "大年三十", "除夕", "春节", "大年初一", "大年初二", "大年初三", "正月十五", "寒假", "清明节", "五一节", "劳动节", "儿童节", "暑假", "中秋节", "国庆节", "圣诞节", "假期", "休息日" };

    foreach (string m in shuzu_danwei_time1)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time2)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time3)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time4)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time5)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }
}

//找时间(年月日时分,布置框架)
void SearchTime2(string str)
{
    //找年月日时分
    string TimeDanwei = "";

    if (str.Contains("年"))
    {
        TimeDanwei = "年";
        FindTime_year = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("月"))
    {
        TimeDanwei = "月";
        FindTime_month = SearchTime3(str, TimeDanwei);
        if (num_type == "汉字型数字")
        {
            FindTime_month = SearchNum3(FindTime_month);
        }
    }
    if (str.Contains("日"))
    {
        TimeDanwei = "日";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("点"))
    {
        TimeDanwei = "点";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("分"))
    {
        TimeDanwei = "分";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
}

//找时间(年月日时分,具体找)
string SearchTime3(string str, string TimeDanwei)
{
    //找数字
    string num = "";
    string[] shuzu_num = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
    string[] shuzu_num_cn = new string[] { "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "零", "十", "百", "千", "万" };

    //数量单位字符左边的字符串
    string WordLeft = str.Substring(0, str.IndexOf(TimeDanwei));
    //找阿拉伯数字,例如1、2、3这类数字
    //逐一处理该字符左边的每个字符
    int WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
    string temp = "";
    //从右向左,逐字截取
    for (int j = WordleftLength; j > 0; j--)
    {
        temp = WordLeft.Substring(j - 1, 1);//每次截取的一个字符

        //从右到左,遇到不是数字的时候,就退出循环
        if (temp != "1" && temp != "2" && temp != "3" && temp != "4" && temp != "5" && temp != "6" && temp != "7" && temp != "8" && temp != "9" && temp != "0")
        {
            break;
        }

        foreach (string m in shuzu_num)//判断这个截取的字符是否在数字数组中
        {
            if (temp == m)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
            {
                //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                if (num == "")
                {
                    num = temp;
                }
                else
                {
                    num = temp + num;
                }
                num_type = "阿拉伯数字";

            }
        }
    }

    if (num == "")//没有找到阿拉伯数字
    {
        //找汉字型数字,例如一、二、三
        WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
        temp = "";
        //从右向左,逐字截取
        for (int j = WordleftLength; j > 0; j--)
        {
            temp = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
            foreach (string m2 in shuzu_num_cn)//判断这个截取的字符是否在数字数组中
            {
                if (temp == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
                {
                    //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                    if (num == "")
                    {
                        num = temp;
                    }
                    else
                    {
                        num = temp + num;
                    }
                    num_type = "汉字型数字";
                }
            }
        }
    }

    if (num != "")
    {
        return num;
    }
    else
    {
        return "";
    }

}

//显示最终输出结果
void ShowResult()
{
    UnityEngine.Debug.Log("第" + dan_num + "句:" + danju[dan_num-1]);
    UnityEngine.Debug.Log("句型:" + SentenceType);

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("语态:" + yutai);
    }
    else if (SentenceType == "双宾语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("间接宾语:" + FindJianObject);
        UnityEngine.Debug.Log("直接宾语:" + FindZhiObject);
    }
    else if (SentenceType == "宾语补足语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("宾语补足语动词:" + FindBuVerb);
        UnityEngine.Debug.Log("宾语补足语名词:" + FindBuNoun);
    }
    else if (SentenceType == "只有性质状态")
    {
        UnityEngine.Debug.Log("只有性质状态:" + dan);
    }

    UnityEngine.Debug.Log("动词发生概率:" + VerbRate);

    //显示名词所有格
    if (SubjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("主语的名词所有格:" + SubjectSuoyouge);
    }
    if (ObjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语的名词所有格:" + ObjectSuoyouge);
    }
    /*
    if (JianSuoyouge != "")
    {
        UnityEngine.Debug.Log("间接宾语的名词所有格:" + JianSuoyouge);
    }
    if (ZhiSuoyouge != "")
    {
        UnityEngine.Debug.Log("直接宾语的名词所有格:" + ZhiSuoyouge);
    }
    if (BuSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语补足语的名词所有格:" + BuSuoyouge);
    }
    */

    //显示形容词
    if (SubjectAdj != "")
    {
        UnityEngine.Debug.Log("主语的形容词:" + SubjectAdj);
    }
    if (ObjectAdj != "")
    {
        UnityEngine.Debug.Log("宾语的形容词:" + ObjectAdj);
    }
    /*
    if (JianAdj != "")
    {
        UnityEngine.Debug.Log("间接宾语的形容词:" + JianAdj);
    }
    if (ZhiAdj != "")
    {
        UnityEngine.Debug.Log("直接宾语的形容词:" + ZhiAdj);
    }
    if (BuAdj != "")
    {
        UnityEngine.Debug.Log("宾语补足语的形容词:" + BuAdj);
    }
    */

    //显示数词
    if (SubjectNum != "")
    {
        UnityEngine.Debug.Log("主语的数词:" + SubjectNum);
    }
    if (ObjectNum != "")
    {
        UnityEngine.Debug.Log("宾语的数词:" + ObjectNum);
    }
    /*
    if (JianNum != "")
    {
        UnityEngine.Debug.Log("间接宾语的形容词:" + JianNum);
    }
    if (ZhiNum != "")
    {
        UnityEngine.Debug.Log("直接宾语的形容词:" + ZhiNum);
    }
    if (BuNum != "")
    {
        UnityEngine.Debug.Log("宾语补足语的形容词:" + BuNum);
    }
    */

    //显示时间:
    /*
    string FindTime_year = "";//要找的时间:年
    string FindTime_month = "";//要找的时间:月
    string FindTime_day = "";//要找的时间:日
    string FindTime_hour = "";//要找的时间:小时
    string FindTime_minute = "";//要找的时间:分钟
    string FindTime2 = "";//要找的时间(文字形式,例如下午、星期一)
    */
    if (FindTime_year != "")
    {
        UnityEngine.Debug.Log("年:" + FindTime_year);
    }
    if (FindTime_month != "")
    {
        UnityEngine.Debug.Log("月:" + FindTime_month);
    }
    if (FindTime_day != "")
    {
        UnityEngine.Debug.Log("日:" + FindTime_day);
    }
    if (FindTime_hour != "")
    {
        UnityEngine.Debug.Log("时(几点):" + FindTime_hour);
    }
    if (FindTime_minute != "")
    {
        UnityEngine.Debug.Log("分(几分):" + FindTime_minute);
    }
    if (FindTime2 != "")
    {
        UnityEngine.Debug.Log("时间:" + FindTime2);
    }

    //tmpText.text = mes;

    //清空变量
    FindSubject = "";
    FindVerb = "";
    FindObject = "";
    FindBuVerb = "";
    FindBuNoun = "";
    FindJianObject = "";
    FindZhiObject = "";
    yutai = "";
    SubjectSuoyouge = "";
    ObjectSuoyouge = "";
    /*
    JianSuoyouge = "";
    ZhiSuoyouge = "";
    BuSuoyouge = "";
    */
}

}

第六章

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//Canvas框显示输入框和输出框所需
using TMPro;//Text Mesh Pro文字控件所需
using Mono.Data.Sqlite;//连接sqlite数据库所需

public class sqlitecon : MonoBehaviour
{
//输入和输出
public TMP_InputField inputField;//输入框对象(把层级面板上的输入框控件拖动到此框里)
string shuru = "";//输入框内容
//public TMP_Text tmpText;//输出框对象(把层级面板上的输出框控件拖动到此框里)
//string mes;//输出框内容
//词库
string[] noun = new string[7128];//名词数组,名词数量7128(数据库增加名词后,此处也要修改,以免造成溢出)
string[] verb = new string[5886];//动词数组,动词数量5886(数据库增加动词后,此处也要修改,以免造成溢出)
string[] adj = new string[1777];//形容词数组,形容词数量1777(数据库增加形容词后,此处也要修改,以免造成溢出)
//按标点符号分割句子
string dan = "";//按标点符号分割出的基本单句
string[] danju = new string[100];//单句的数组储存
int dan_num = 1;//第几个单句
//单句里,谓语动词分割出的左右句
string LeftPart = "";//谓语动词的左边句
string RightPart = "";//谓语动词的右边句
//基本单句的语法结构
string FindSubject = "";//主语
string FindVerb = "";//谓语动词
string FindObject = "";//宾语
string FindBuVerb = "";//宾语补足语的动词
string FindBuNoun = "";//宾语补足语的名词
string FindJianObject = "";//间接宾语
string FindZhiObject = "";//直接宾语
//名词所有格(例如张三的猫,张三就是名词所有格,“的”字就不写了)
string SubjectSuoyouge = "";//主语的名词所有格
string ObjectSuoyouge = "";//宾语的名词所有格
string JianSuoyouge = "";//间接宾语的名词所有格
string ZhiSuoyouge = "";//直接宾语的名词所有格
string BuSuoyouge = "";//宾语补足语的名词所有格
string TempSuoyouge = "";//临时存放名词所有格
//形容词
string SubjectAdj = "";//主语的形容词
string ObjectAdj = "";//宾语的形容词
string JianAdj = "";//间接宾语的形容词
string ZhiAdj = "";//直接宾语的形容词
string BuAdj = "";//宾语补足语的形容词
//数词
string SubjectNum = "";//主语的数词
string ObjectNum = "";//宾语的数词
string JianNum = "";//间接宾语的数词
string ZhiNum = "";//直接宾语的数词
string BuNum = "";//宾语补足语的数词
//语法结构的相关描述
string SentenceType = "";//句型
string yutai = "";//语态:主动语态还是被动语态
string VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
//名词槽(名词之间相互覆盖时用)
string NounBox1 = "";//名词槽1
string NounBox2 = "";//名词槽2
string NounBox3 = "";//名词槽3
string NounBox4 = "";//名词槽4
//动词槽(动词之间相互覆盖时用)
string VerbBox1 = "";//动词槽1
string VerbBox2 = "";//动词槽2
string VerbBox3 = "";//动词槽3
string VerbBox4 = "";//动词槽4
//数词和时间
string FindNum = "";//要找的数词的数字
string NumDanwei = "";//数词单位
string FindTime_year = "";//要找的时间:年
string FindTime_month = "";//要找的时间:月
string FindTime_day = "";//要找的时间:日
string FindTime_hour = "";//要找的时间:小时
string FindTime_minute = "";//要找的时间:分钟
string FindTime2 = "";//要找的时间(文字形式,例如下午、星期一)
string num_type = "";//数字类型:阿拉伯数字(例如1、2、3)还是汉字型数字(例如一、二、三)
//地点
string didian = "";

// Start is called before the first frame update
void Start()
{
    ciku();//填充词库
    inputField.onEndEdit.AddListener(OnInputEndEdit);//输入完成后,对回车键的响应(按回车键发送)
}

// Update is called once per frame
void Update()
{

}

//填充词库(数据库的词库填充到数组中)
void ciku()
{
    //生成游戏后,需要把sqlite数据库复制到生成的游戏的文件夹里,那个文件夹自动生成的这个数据库是0kb,无效的,需要重新复制过去
    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    int i = 0;

    //填充名词数组
    //第一步:sql指令
    string sqlQuery = "SELECT word_col FROM noun";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充名词数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();
    while (dbReader.Read())
    {
        noun[i] = dbReader.GetValue(0).ToString();//GetValue(0)表示结果集的第一列,因为只查询了一列,所以返回的结果集就一列
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示名词数量

    //填充动词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM verb";//sql指令
    //第二步:执行指令
    //dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        verb[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示动词数量

    //填充形容词数组
    //第一步:sql指令
    sqlQuery = "SELECT word_col FROM adj";//sql指令
    //第二步:执行指令
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充动词数组
    dbReader = dbCommand.ExecuteReader();
    i = 0;
    while (dbReader.Read())
    {
        adj[i] = dbReader.GetValue(0).ToString();
        i++;
    }
    dbReader.Close();
    //UnityEngine.Debug.Log(i);//显示形容词数量

    dbConnection.Close();//关闭数据库连接
}

//输入完成后,按回车键发送,便开始执行此函数
void OnInputEndEdit(string value)
{
    shuru = inputField.text;//输入框的内容
    SplitSay();//按标点符号,分割输入内容
}

//按标点符号,分割输入内容,分割成基本单句
void SplitSay()
{
    /*
    输入的内容可能是一大段内容,需要分割成一个个基本单句,从而逐一处理。
    基本单句就是主语-谓语-宾语,或主语-谓语-间接宾语-直接宾语,或主语-谓语-宾语-宾语补足语,这类语法上的基本单句。
    那就需要按逗号分割句子,按句号分割句子,才能拆分成一个个这样的基本单句。

    按逗号分割句子:
    string str = "早晨,中午,下午";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符,分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    按逗号和句号分割句子:
    string str = "早晨,中午。下午,傍晚";
    string word = ",";
    string[] shuzu = str.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
    foreach (string part in shuzu)
    {
        string word2 = "。";
        string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
        foreach (string part2 in shuzu2)
        {
            UnityEngine.Debug.Log(part2);
        }
    }

    计算标点符号的数量:
    string str = "早晨,中午。下午,傍晚";
    string temp = "";

    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = str.Length;//句子长度

    temp = str.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量

    temp = str.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    以上注释掉的内容,只是解释说明,下面才是运行的程序:
    */

    //计算标点符号的数量
    string temp = "";
    int dou = 0;//逗号数量
    int ju = 0;//句号数量
    int str_length = shuru.Length;//句子长度
    //计算逗号的数量
    temp = shuru.Replace(",", "");//把逗号替换为空无,就是去掉逗号
    int str_length_delete_dou = temp.Length;//去掉逗号后,句子的长度
    dou = str_length - str_length_delete_dou;//两者相减,就是逗号的数量
    //计算句号的数量
    temp = shuru.Replace("。", "");//把句号替换为空无,就是去掉句号
    int str_length_delete_ju = temp.Length;//去掉句号后,句子的长度
    ju = str_length - str_length_delete_ju;//两者相减,就是句号的数量

    //按标点符号分割句子
    if (dou > 0 || ju > 0)//逗号大于0或句号大于0,就是输入的内容有标点符号
    {
        string word = ",";//分割符:中文的逗号
        string[] shuzu = shuru.Split(word);//按word指定的分隔符(逗号),分割字符串,并存入数组中
        foreach (string part in shuzu)//逐个处理
        {
            string word2 = "。";//分割符:中文的句号
            string[] shuzu2 = part.Split(word2);//按word2指定的分隔符(句号),分割字符串,并存入数组中
            foreach (string part2 in shuzu2)//逐个处理
            {
                dan = part2;//基本单句已经分割出来了,在part2里,并赋值给dan(基本单句)
                danju[dan_num - 1] = part2;//数组从0开始计算,而danju从1开始计算,所以换算上要减1
                ClearData();//清除上次的变量数据
                //UnityEngine.Debug.Log("单句:" + dan);
                SearchVerb(dan);//找谓语动词(这是单句处理的第一步)
                dan = "";
                dan_num++;
            }
        }
    }
    else//输入的内容,没有标点符号
    {
        if (shuru != "")//有输入的内容
        {
            dan = shuru;//输入的内容就是一个基本单句
            danju[0] = shuru;
            SearchVerb(dan);//找谓语动词
            dan = "";
        }
    }

    //后面分析一句话,记着用变量dan,不要再用变量shuru了,因为变量shuru是整段话(可以是多句话组成),变量dan才是分割出的单句
}

//清除上次循环(基本单句处理)的变量数据
void ClearData()
{
    FindSubject = "";//主语
    FindVerb = "";//谓语动词
    FindObject = "";//宾语
    FindBuVerb = "";//宾语补足语的动词
    FindBuNoun = "";//宾语补足语的名词
    FindJianObject = "";//间接宾语
    FindZhiObject = "";//直接宾语
    SubjectSuoyouge = "";//主语的名词所有格
    ObjectSuoyouge = "";//宾语的名词所有格
    TempSuoyouge = "";//临时存放名词所有格
    SubjectAdj = "";//主语的形容词
    ObjectAdj = "";//宾语的形容词
    SubjectNum = "";//主语的数词
    ObjectNum = "";//宾语的数词
    SentenceType = "";//句型
    yutai = "";//语态:主动语态还是被动语态
    VerbRate = "";//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
    NounBox1 = "";//名词槽1
    NounBox2 = "";//名词槽2
    NounBox3 = "";//名词槽3
    NounBox4 = "";//名词槽4
    VerbBox1 = "";//动词槽1
    VerbBox2 = "";//动词槽2
    VerbBox3 = "";//动词槽3
    VerbBox4 = "";//动词槽4
    FindNum = "";
    NumDanwei = "";
    num_type = "";
}

//找谓语动词
void SearchVerb(string str)
{
    string jieguo = "不包含";//默认值是不包含动词
    int m = verb.Length;//动词数组的长度,也就是有多少个动词

    LeftPart = "";
    RightPart = "";
    VerbBox1 = "";
    VerbBox2 = "";
    VerbBox3 = "";
    VerbBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和动词的包含关系
        就是用句子和动词数组的动词,一一比对,来判断是否包含动词
        n的值从0逐渐增长到动词数组的动词数量值,这样数组也就经历了所有动词
        */
        if (str.Contains(verb[n]))//包含动词
        {
            if (VerbJudge(str, verb[n]) == true)//是动词,不是名词
            {
                jieguo = "包含";
                FindVerb = verb[n];//找到了动词
                VerbCover(str, verb[n]);//把动词放入动词槽里,看看有几个动词
                VerbOrder();//动词排序
                VerbJoin();//动词结合
            }
        }
    }

    if (jieguo == "包含")//包含动词
    {
        VerbRateJudge();//动词发生概率:肯定、偏向肯定、不确定、偏向否定、否定
        SentenceType = SentenceJudge();//判断句型(仅从动词情况来判断句型,还不是完全清楚的判断,之后还需进一步判断)
        SplitSentence();//以谓语动词为分割符,来分割句子
    }
}

//以谓语动词为分割符,来分割句子
void SplitSentence()
{
    /*
    对于主谓宾句型,先找出动词,然后以动词为分割符号,分割句子。动词左边分割出的句子的名词就是主语,动词右边分割出的句子的名词就是宾语
    先举个例子简单说明一下字符串分割的基本原理:
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string word = "嘲笑";//指定词
    string res = "";//结果
    int chang = 0;//全句长度
    int index = 0;//指定词语的起始位置
    int LastIndex = 0;//指定词语最后一个字符在全句中的位置
    int jie = 0;//临时变量

    //计算全句长度
    chang = str.Length;//显示字符个数,从1开始计算
    //计算指定字符在全句中的位置
    index = str.IndexOf(word) + 1;//默认从0计算,例如第2个字符,显示为1,而不是2。为了调整为1开始计算,所以加1
    //计算指定词语最后一个字符在全句中的位置
    LastIndex = str.IndexOf(word) + word.Length;

    //截取第3个字符右边的1个字符
    Substring(开始位置, 向右截取长度),从1开始计算,不是0
    res = str.Substring(3,1); //从第3个字符开始,向右截取1个字符

    //截取指定字符右边的全部字符
    jie = chang - LastIndex;//截取长度 = 全句长度 - 指定词语最后一个字符的位置长度
    res = str.Substring(LastIndex, jie);
    res = str.Substring(str.IndexOf(word) + word.Length, str.Length - (str.IndexOf(word) + word.Length));//展开形式

    //截取指定字符左边的全部字符
    res = str.Substring(0, index);//从句子开始的0位置,截取长度是指定字符的位置长度
    res = str.Substring(0, str.IndexOf(word));//变化形式

    //截取两个指定字符之间的全部字符
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式

    //数组形式截取字符
    //前面定义了:str = "白色的猫吃黑色的鼠"; word = "吃";
    string[] shuzu = str.Split(word);//按指定分割符分割字符串,并存入数组中
    UnityEngine.Debug.Log(shuzu[0]);//显示:白色的猫
    UnityEngine.Debug.Log(shuzu[1]);//显示:黑色的鼠
    //或逐一显示数组全部
    foreach (string part in shuzu)
    {
        UnityEngine.Debug.Log(part);
    }

    以上注释掉的内容,只是解释原理,下面是运行的程序:
    */

    //也可能找到一个动词(主谓宾句型),也可能找到两个动词(宾语补足语句型)
    if (VerbBox1 != "" && VerbBox2 == "")//只找到1个动词,那就是谓语动词
    {
        FindVerb = VerbBox1;
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//找到2个动词
    {
        FindVerb = VerbBox1;//位次在前面的动词是谓语动词
        FindBuVerb = VerbBox2;//位次在后面的动词是宾语补足语动词
    }

    //谓语动词左边句(LeftPart)和谓语动词右边句(RightPart)是一个重要的转折,为以后的句子处理奠定了基础
    LeftPart = dan.Substring(0, dan.IndexOf(FindVerb));
    RightPart = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.Length - (dan.IndexOf(FindVerb) + FindVerb.Length));

    /*
    例如句子(dan)是白色的猫吃黑色的鼠
    find_word:吃
    LeftPart:白色的猫
    RightPart:黑色的鼠
    UnityEngine.Debug.Log(find_verb);//谓语动词
    UnityEngine.Debug.Log(LeftPart);//谓语动词的左边句
    UnityEngine.Debug.Log(RightPart);//谓语动词的右边句
    */

    /*
    省略主语有两种情况:一种是主动语态省略主语,例如“跳过去”,全句指“你跳过去”。另一种是被动语态省略主语,例如“张三被打了”,没说谁打了张三,这里张三是宾语。如果说“李四打了张三”,李四就是主语。
    被动语态的标志是“被”字,如果没有“被”字,而且省略了主语,就是主动语态省略主语的情况,那么这种情况下,主语应该填什么呢?例如“过来”,一般指“你过来”,但“走吧”一般指“我们走吧”。所以程序要根据具体的动词来判断省略的主语应该填什么。但是动词太多,每个动词都要设置省略的主语判断,太麻烦。所以省略主语,按最通常情况,就默认填“你”字,作为主语。如果主语是“我们”而不是“你”字,就不该省略主语。
    被动语态应该还原为主动语态去理解,但被动语态往往没有主语,那么默认主语应该填什么呢?毕竟不知道主语,那就填“事物”这个词作为主语。
    程序分析句子时,被动语态的主语位置的词,是宾语。例如“李四被打了”,李四在谓语动词左边句,程序会把李四当成主语,但在被动语态句里,李四不是主语,所以有“被”字的时候,主语要挪动到宾语位置,然后在主语位置补充“事物”这个词,作为主语。
    但是有些时候,被动语态的主语是说明了的,例如“李四被张三打了”就还原为主动语态“张三打了李四”,张三做主语,而不是填“事物”做主语。
    简而言之,被动语态里,主语放到了宾语位置,宾语放到了主语位置,所以变为主动语态时,要把宾语挪回主语位置,主语挪回宾语位置。
    如果被动语态有主语,例如“李四被张三打了”,那么主语(张三)位于“被”字与谓语动词之间。
    那么谓语动词左边句中,又分为“被”字左边句和“被”字右边句,被字左边句里的名词是宾语,被字右边句里的名词是主语。
    */
    yutai = "主动";//默认主动语态
    if (SentenceType == "主谓宾" && dan.Contains("被"))//语句中包含“被”字
    {
        if (dan.Contains("被子") == false && dan.Contains("被褥") == false)//语句中包含“被”字,但不是“被子”这个名词,才能指被动语态的“被”字
        {
            yutai = "被动";//被动语态
        }
        else
        {
            yutai = "主动";//主动语态
        }
    }
    else//语句中没有包含“被”字
    {
        yutai = "主动";//主动语态
    }

    //对谓语动词左边句(LeftPart)的处理
    if (LeftPart != "")//谓语动词左边句有内容
    {
        if (yutai == "主动")//主动语态
        {
            //找名词(主语)和名词所有格
            FindSubject = SearchNoun(LeftPart);//在谓语动词左边句找名词(主语)
            if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
            {
                SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                TempSuoyouge = "";//置空
            }
            //找形容词(主语的形容词)
            SubjectAdj = SearchAdj(LeftPart);
            //找数词
            FindNum = "";
            NumDanwei = "";
            num_type = "";
            SearchNum(LeftPart);
            SubjectNum = FindNum + NumDanwei;
            //找时间
            SearchTime1(LeftPart);//找时间:文字形式,例如今天、星期一
            SearchTime2(LeftPart);//找时间:年月日时分
        }
        else if (yutai == "被动")//被动语态
        {
            string bei = "被";
            string BeiLeft = "";
            string BeiRight = "";

            //被字左边句
            BeiLeft = LeftPart.Substring(0, LeftPart.IndexOf(bei));
            if (BeiLeft != "")
            {
                FindObject = SearchNoun(BeiLeft);//被字左边句的名词是宾语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(BeiLeft);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(BeiLeft);
                ObjectNum = FindNum + NumDanwei;
                //找时间
                SearchTime1(BeiLeft);//找时间:文字形式,例如今天、星期一
                SearchTime2(BeiLeft);//找时间:年月日时分
            }

            //被字右边句
            BeiRight = LeftPart.Substring(LeftPart.IndexOf(bei) + bei.Length, LeftPart.Length - (LeftPart.IndexOf(bei) + bei.Length));
            
            if (BeiRight != "")
            {
                FindSubject = SearchNoun(BeiRight);//被字右边句的名词是主语
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    SubjectSuoyouge = TempSuoyouge;//是主语的名词所有格
                    TempSuoyouge = "";//置空
                }
                //找形容词(主语的形容词)
                SubjectAdj = SearchAdj(BeiRight);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(BeiRight);
                SubjectNum = FindNum + NumDanwei;
            }
            //如果没有主语,就填补“事物”这个词作为主语,毕竟被动语态经常没有主语
            if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
            {
                FindSubject = "事物";
            }
        }
    }

    //如果省略主语,则填补省略的主语
    if (yutai == "主动")
    {
        if (FindSubject == "" || FindSubject == null)//主语为空或主语不存在
        {
            FindSubject = "你";//默认填补“你”字做主语
        }
    }

    //对谓语动词右边句(RightPart)的处理
    if (SentenceType == "双宾语")//双宾语句型
    {
        FindObject = SearchNoun(RightPart);//找名词
        if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
        {
            ZhiSuoyouge = TempSuoyouge;//是直接宾语的名词所有格(暂且这样设置)
            TempSuoyouge = "";//置空
        }

        //谓语动词右边句里,没有第二个宾语名词,那就不是双宾语
        //例如虽然有双宾语句的标志动词“教”字,但他教我数学,是双宾语句,而他教书,是主谓宾句型
        if (NounBox2 == "")
        {
            SentenceType = "主谓宾";
            ZhiSuoyouge = "";//既然不作为双宾语句型了,原来的直接宾语所有格也就要清空了
        }
        else
        {
            //直接宾语的定语(形容词、数词、名词所有格),在间接宾语和直接宾语之间
            //例如张三给李四红色的苹果,李四是间接宾语,苹果是直接宾语,红色的是形容词
            if (FindJianObject != "" && FindZhiObject != "")//间接宾语和直接宾语不为空
            {
                string BewteenPart = "";
                BewteenPart = RightPart.Substring(RightPart.IndexOf(FindJianObject) + FindJianObject.Length, RightPart.IndexOf(FindZhiObject) - (RightPart.IndexOf(FindJianObject) + FindJianObject.Length));
                if (BewteenPart != "")
                {
                    //找形容词
                    ZhiAdj = SearchAdj(BewteenPart);
                    //找数词
                    FindNum = "";
                    NumDanwei = "";
                    num_type = "";
                    SearchNum(BewteenPart);
                    ZhiNum = FindNum + NumDanwei;
                }
            }
            //间接宾语的定语在谓语动词和间接宾语之间,对于谓语动词右边句,也就是句子开始到间接宾语之间
            //例如张三给美丽的李四苹果,李四是间接宾语,美丽的是形容词
            if (FindJianObject != "")//间接宾语不为空
            {
                string PartLeft = "";
                PartLeft = RightPart.Substring(0, RightPart.IndexOf(FindJianObject));
                if (PartLeft != "")
                {
                    //找形容词
                    JianAdj = SearchAdj(PartLeft);
                    //找数词
                    FindNum = "";
                    NumDanwei = "";
                    num_type = "";
                    SearchNum(PartLeft);
                    JianNum = FindNum + NumDanwei;
                }
            }

            ShowResult();//显示最终输出结果
        }
    }

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        if (RightPart != "")
        {
            if (yutai == "主动")
            {
                //找名词和名词所有格
                FindObject = SearchNoun(RightPart);//在谓语动词右边句找名词(宾语)
                if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
                {
                    ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
                    TempSuoyouge = "";//置空
                }

                //找形容词(宾语的形容词)
                ObjectAdj = SearchAdj(RightPart);
                //找数词
                FindNum = "";
                NumDanwei = "";
                num_type = "";
                SearchNum(RightPart);
                ObjectNum = FindNum + NumDanwei;
            }
        }

        ShowResult();//显示最终输出结果
    }

    if (SentenceType == "宾语补足语")//宾语补足语句型
    {
        //谓语动词到宾语补足语动词之间的部分里的名词,是宾语名词
        string temp = "";
        //截取谓语动词FindVerb和宾语补足语动词FindBuVerb之间的部分
        temp = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.IndexOf(FindBuVerb) - (dan.IndexOf(FindVerb) + FindVerb.Length));
        FindObject = SearchNoun(temp);//找名词
        if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
        {
            ObjectSuoyouge = TempSuoyouge;//是宾语的名词所有格
            TempSuoyouge = "";//置空
        }
        //宾语补足语右边句的名词,是宾语补足语名词,而不是宾语名词
        int WordLastChar = dan.IndexOf(FindBuVerb) + FindBuVerb.Length;//宾语补足语动词最后一个字符的位置
        if (WordLastChar < dan.Length)//宾语补足语动词最后一个字符的位置没有到全句末尾,就是说宾语补足语动词后面还有内容,那就是宾语补足语名词
        {
            //截取宾语补足语动词右边的内容
            string BuRight = dan.Substring(dan.IndexOf(FindBuVerb) + FindBuVerb.Length, dan.Length - (dan.IndexOf(FindBuVerb) + FindBuVerb.Length));
            FindBuNoun = SearchNoun(BuRight);//找名词(上次写错了,写成temp了,那就把宾语也当要找的名词了)
            if (TempSuoyouge != "")//找名词时,顺便还找到了名词所有格
            {
                BuSuoyouge = TempSuoyouge;//是宾语补足语的名词所有格
                TempSuoyouge = "";//置空
            }
            //宾语补足语名词的定语(形容词、数词、名词所有格)在宾语补足语动词的右边(BuRight)
            //例如张三让李四打扫蓝色的房间,打扫是宾语补足语的动词,房间是宾语补足语的名词,蓝色的是形容词
            //找形容词
            BuAdj = SearchAdj(BuRight);
            //找数词
            FindNum = "";
            NumDanwei = "";
            num_type = "";
            SearchNum(BuRight);
            BuNum = FindNum + NumDanwei;
        }

        ShowResult();//显示最终输出结果
    }

    /*
    靠句子包含的词直接与词库的词对比,来找主语(名词)、谓语(动词)、宾语(名词),会有问题:

    第一个问题:熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    所以创建一个函数:WordCover(覆盖)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。

    第二个问题:熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    对于第二个问题的解决方法:
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    所以创建一个de函数。

    第三个问题:“学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。“压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。
    所以创建一个VerbJudge函数。
    */
}

//找名词(也包括找名词所有格)
string SearchNoun(string PartSentence)
{
    string jieguo = "不包含";//默认值是不包含
    int m = noun.Length;//名词数组的长度,也就是有多少个名词

    //for循环前,先把词语槽清空,因为for循环时,调用的函数WordCover要用词语槽,来完成词语的覆盖和吸收
    NounBox1 = "";
    NounBox2 = "";
    NounBox3 = "";
    NounBox4 = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和名词的包含关系
        就是用句子和名词数组的名词,一一比对,来判断是否包含名词
        n的值从0逐渐增长到名词数组的名词数量值,这样数组也就经历了所有名词
        */
        if (PartSentence.Contains(noun[n]))//句子包含名词
        {
            jieguo = "包含";
            //找到的名词不是名词所有格,也不是地点,才是主语或宾语的名词
            if (de(PartSentence, noun[n]) == false)//找到的名词右边的第一个字符不是“的”字,才算是名词,否则是名词所有格
            {
                if (difang(PartSentence, noun[n]) == false)//找到的名词左边的第一个字符,不是地点动词
                {
                    NounCover(noun[n]);
                }
                else//名词左边第一个字是“在”或“到”或“去”或“来”,那么这个名词就是地点,而不是作为主语名词
                {
                    didian = noun[n];//找到的地点
                }
            }
            else//名词右边的第一个字是“的”字,就意味着是名词所有格
            {
                TempSuoyouge = noun[n];//找到的名词所有格
            }
        }
    }

    if (jieguo == "包含")//找到了名词
    {
        NounOrder();//名词排序
        //名词要先排序,才能合并名词,否则“足球”和“学校”的顺序如果变成“学校”和“足球”,那就合并成“学校足球”这个词了,而不是“足球学校”

        //如果双宾语句型进行名词合并,就可能会把间接宾语名词和直接宾语名词合并到一起,成为一个名词,就不对了
        if (SentenceType != "双宾语")//不是双宾语句型
        {
            NounJoin();//名词合并,例如把“足球”和“学校”合并成“足球学校”这一个名词
        }
        else if (SentenceType == "双宾语")//是双宾语句型
        {
            //但是如果现在处理的是双宾语结构的谓语动词左边句,也就是处理主语,还是可以名词合并的
            if (dan.IndexOf(NounBox1) < dan.IndexOf(FindVerb))
            {
                NounJoin();//名词合并
            }
        }

        return NounBox1;
    }
    else
    {
        return "";
    }
}

//名词之间的覆盖
void NounCover(string FindWord)
{
    /*
    熊猫吃竹子,这句话里你感觉有感觉有两个名词:熊猫、竹子,但是电脑会找出四个名词:熊猫、熊、猫、竹子。
    对于第一个问题的解决方法:
    新找到的长词(熊猫)覆盖已找到的短词(熊、猫)。
    已找到的长词(熊猫)吸收新找到的短词(熊、猫)。
    词语槽(NounBox)存放这些找到词,以实现覆盖和吸收。
    做了4个词语槽(NounBox),为了以后适应复杂的句子,但简单的主谓宾句型,一个词语槽就够了。
    */
    if (NounBox1 == "" && FindWord != "")//词语槽还是空的,说明这是找到的第一个词
    {
        NounBox1 = FindWord;//找到的第1个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽2了
    }
    else if (NounBox1 != "" && FindWord != "")//词语槽1已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox1))//覆盖:例如找到的词(FindWord)是熊猫,词语槽1(NounBox1)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽2了
        }
        else if (NounBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽1(NounBox1)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,不要这个词了,免得填到词语槽2了
        }
    }

    if (NounBox2 == "" && FindWord != "")//词语槽2是空的,FindWord经过词语槽1,没有覆盖或吸收,说明FindWord和词语槽1的词无关,例如FindWord是竹子
    {
        NounBox2 = FindWord;//找到的第2个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽3了
    }
    else if (NounBox2 != "" && FindWord != "")//词语槽2已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox2))//覆盖:例如找到的词(FindWord)是熊猫,词语槽2(NounBox2)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (NounBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽2(NounBox2)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (NounBox3 == "" && FindWord != "")//词语槽3是空的,FindWord经过词语槽2,没有覆盖或吸收,说明FindWord和词语槽2的词无关,例如FindWord是竹子
    {
        NounBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (NounBox3 != "" && FindWord != "")//词语槽3已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox3))//覆盖:例如找到的词(FindWord)是熊猫,词语槽3(NounBox3)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (NounBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽3(NounBox3)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (NounBox4 == "" && FindWord != "")//词语槽4是空的,FindWord经过词语槽3,没有覆盖或吸收,说明FindWord和词语槽3的词无关,例如FindWord是竹子
    {
        NounBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (NounBox4 != "" && FindWord != "")//词语槽4已经有找到的词了,例如已经放入熊或猫或熊猫,而现在又找到词熊或猫或熊猫
    {
        if (FindWord.Contains(NounBox4))//覆盖:例如找到的词(FindWord)是熊猫,词语槽4(NounBox4)的词是熊,“熊猫”包含(Contain)“熊”字
        {
            NounBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (NounBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是熊,词语槽4(NounBox4)的词是熊猫,“熊”字属于“熊猫”
        {
            FindWord = "";//置空
        }
    }

    /*
    “足球”这个词,会找到三个名词:足、球、足球。
    先找到第一个词:足,放入NounBox1。
    再找到第二个词:球,放入NounBox2。
    再找到第三个词:足球,会覆盖NounBox1的“足”字,但却无法覆盖NounBox2的球字。
    因此程序做一些改进。

    但如果幸运的:
    先找到第一个词:足球,放入NounBox1。
    再找到第二个词:足,被NounBox1“足球”这个词吸收,不会进入到NounBox2。
    再找到第三个词:球,被NounBox1“足球”这个词吸收,也不会进入到NounBox2。
    那么就不用执行下面这段程序了。
    先找到那个词是不确定的,词库词语可能按笔画排序,也可能按首字母排序,就不知道先找到那个词了。

    如果输入的是“皮球”这个词,而词库里没有“皮球”这个词,但有“皮”字和“球”字这两个词。
    那么,NounBox1是“皮”字,NounBox2是“球”字,或NounBox1是“球”字,NounBox2是“皮”字,没有覆盖和吸收。
    */
    if (NounBox1.Contains(NounBox2))//NounBox1包含了NounBox2,例如“足球”包含“球”字
    {
        NounBox2 = "";
        if (NounBox3 != "")
        {
            NounBox2 = NounBox3;
            NounBox3 = "";
        }
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox2.Contains(NounBox3))//NounBox2包含了NounBox3
    {
        NounBox3 = "";
        if (NounBox4 != "")
        {
            NounBox3 = NounBox4;
            NounBox4 = "";
        }
    }
    if (NounBox3.Contains(NounBox4))//NounBox3包含了NounBox4
    {
        NounBox4 = "";
    }
}

//动词之间的覆盖
void VerbCover(string str,string FindWord)
{
    if (VerbBox1 == "" && FindWord != "")//动词槽还是空的,说明这是找到的第一个词
    {
        VerbBox1 = FindWord;//找到的第1个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽2了
    }
    else if (VerbBox1 != "" && FindWord != "")//动词槽1已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox1))//覆盖:例如找到的词(FindWord)是敲打,动词槽1(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox1 = FindWord;//词语槽1的词:长词覆盖短词,例如“敲打”覆盖“打”
            FindWord = "";//置空,免得填到动词槽2了
        }
        else if (VerbBox1.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽1(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,不要这个词了,免得填到动词槽2了
        }
    }

    if (VerbBox2 == "" && FindWord != "")//动词槽2是空的,FindWord经过动词槽1,没有覆盖或吸收,说明FindWord和动词槽1的词无关,例如FindWord是喜欢
    {
        VerbBox2 = FindWord;//找到的第2个词,放入动词槽
        FindWord = "";//置空,免得填到动词槽3了
    }
    else if (VerbBox2 != "" && FindWord != "")//动词槽2已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox2))//覆盖:例如找到的词(FindWord)是敲打,动词槽2(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox2 = FindWord;//词语槽2的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽3了
        }
        else if (VerbBox2.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽2(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽3了
        }
    }

    if (VerbBox3 == "" && FindWord != "")//动词槽3是空的,FindWord经过动词槽1和2,没有覆盖或吸收,说明FindWord和动词槽1、2的词无关,例如FindWord是喜欢
    {
        VerbBox3 = FindWord;//找到的第3个词,放入词语槽
        FindWord = "";//置空,免得填到词语槽4了
    }
    else if (VerbBox3 != "" && FindWord != "")//动词槽3已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox3))//覆盖:例如找到的词(FindWord)是敲打,动词槽3(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox3 = FindWord;//词语槽3的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空,免得填到词语槽4了
        }
        else if (VerbBox3.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽3(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空,免得填到词语槽4了
        }
    }

    if (VerbBox4 == "" && FindWord != "")//动词槽4是空的,FindWord经过动词槽1、2、3,没有覆盖或吸收,说明FindWord和动词槽1、2、3的词无关,例如FindWord是喜欢
    {
        VerbBox4 = FindWord;//找到的第4个词,放入词语槽
        FindWord = "";//置空
    }
    else if (VerbBox4 != "" && FindWord != "")//动词槽4已经有找到的词了,例如已经放入敲打或敲或打,而现在又找到词敲打或敲或打
    {
        if (FindWord.Contains(VerbBox4))//覆盖:例如找到的词(FindWord)是敲打,动词槽4(VerbBox1)的词是打,“敲打”包含(Contain)“打”字
        {
            VerbBox4 = FindWord;//词语槽4的词:长词覆盖短词,例如“熊猫”覆盖“熊”
            FindWord = "";//置空
        }
        else if (VerbBox4.Contains(FindWord))//吸收:例如找到的词(FindWord)是打,动词槽4(VerbBox1)的词是敲打,“打”字属于“敲打”
        {
            FindWord = "";//置空
        }
    }

    /*
    “敲打”这个词,会找到三个动词:敲、打、敲打
    先找到第一个词:敲,放入VerbBox1
    再找到第二个词:打,放入VerbBox2
    再找到第三个词:敲打,会覆盖VerbBox1的“敲”字,但却无法覆盖VerbBox2的“打”字
    因此程序做一些改进。 
    */
    if (VerbBox1.Contains(VerbBox2))//VerbBox1包含了VerbBox2
    {
        VerbBox2 = "";
        if (VerbBox3 != "")
        {
            VerbBox2 = VerbBox3;
            VerbBox3 = "";
        }
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox2.Contains(VerbBox3))//VerbBox2包含了VerbBox3
    {
        VerbBox3 = "";
        if (VerbBox4 != "")
        {
            VerbBox3 = VerbBox4;
            VerbBox4 = "";
        }
    }
    if (VerbBox3.Contains(VerbBox4))//VerbBox3包含了VerbBox4
    {
        VerbBox4 = "";
    }
}

//名词后面是否包含“的”字
bool de(string str,string word)
{
    /*
    熊猫喜欢森林的竹子,这句话动词右边句有两个名词,竹子是宾语,而森林不是宾语,因为森林后边有个“的”字,是名词所有格。
    找到的名词右边的第一个字符,看它是不是“的”字,如果是“的”字,那么这个名词就不是宾语,找主语也是同理。
    
    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }
    UnityEngine.Debug.Log(res);//显示:的
    以上注释掉的内容只是解释原理,下面是运行程序:
    */

    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果
    WordLastChar = str.IndexOf(word) + word.Length;
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
    }

    if (res == "的")
    {
        return true;
    }
    else
    {
        return false;
    }
}

//判断一个字是动词还是名词
bool VerbJudge(string str,string word)
{
    /*
    “学”字是动词,但是在“学生”这个词里,“学”字就变成名词了,还当动词理解,就会错。
    对于第三个问题的解决方法:
    建立词性辨析表:verb_judge
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   学     |   r1    |      生      |
    +----------+---------+--------------+
    |   压     |   l1    |      气      |
    +----------+---------+--------------+
    word_col:判断这个字是动词还是名词,也就是辨析字。
    type_col:r1表示right1,就是指content_col的字是word_col的那个字的右边那1个字,也就是“学生”的“生”字。
    l1表示left1,就是指content_col的字是word_col的那个字的左边那1个字,也就是“气压”的“气”字。
    “压”是本身是动词,但左边那个字是“气”字时,“压”字就变为名词了,也就是名词“气压”的“压”。
    l是字母L的小写,不是数字1。l1是两个不同的字符。

    不容易理解的一处:
    +----------+----------+-------------+
    | word_col | type_col | content_col |
    +----------+---------+--------------+
    |   吹     |   l1    |      电      |
    +----------+---------+--------------+
    “吹”字本身做动词,但在“电吹风”这个词里做名词,但我不用把“电吹风”这个三个字都判断,我只要判断“电吹”两个字就可以了。

    遇到单字动词的时候,先看这个字是否在词性辨析表里,
    如果在,type_col要求是r1(right1,就是要辨析的字的右边1个字符),那就看句子中要辨析的字的右边1个字符是不是符合词性表中的字,
    如果符合,要辨析的字就是名词,而不是动词了。
    例如学生看书,这句话先找到了动词“学”,在词性辨析表里,“学”字的type_col是r1,content_col是“生”字,
    那就在句子中,看“学”字右边的1个字符是不是“生”字,如果是,“学”字就不做动词,而做名词了。

    一个要辨析的字,type_col有四种可能:r1、r2、l1、l2,也就是右边1个字,右边2个字,左边1个字,左边2个字,那就要会四个方法:
    符合r1:找辨析字右边1个字符:res = str.Substring(str.IndexOf(word) + word.Length, 1);
    符合r2:找辨析字右边2个字符:res = str.Substring(str.IndexOf(word) + word.Length, 2);
    符合l1:找辨析字左边1个字符:res = str.Substring(str.IndexOf(word) - 1, 1);
    符合l2:找辨析字左边2个字符:res = str.Substring(str.IndexOf(word) - 2, 1);

    截取指定字符右边1个字符的基本原理:
    string str = "白色的猫吃黑色的鼠";//全句
    string word = "黑色";//指定词
    int index = 0;//指定词的位置(索引)
    int WordLength = 0;//词语长度
    int WordLastChar = 0;//词语最后一个字符的位置
    string res = "";//结果

    WordLength = word.Length;
    index = str.IndexOf(word);

    //指定词语右边1个字符
    WordLastChar = index + WordLength;
    WordLastChar = str.IndexOf(word) + word.Length;//变化形式
    if (WordLastChar < str.Length)
    {
        res = str.Substring(WordLastChar, 1);
        res = str.Substring(str.IndexOf(word) + word.Length, 1);//变化形式

    }
    UnityEngine.Debug.Log(res);//显示:的

    //指定词语左边1个字符
    res = str.Substring(index - 1, 1);
    res = str.Substring(str.IndexOf(word) - 1, 1);//变化形式
    UnityEngine.Debug.Log(res);//显示:吃
    以上注释掉的内容,只是解释原理,下面是运行程序:
    */

    string[] TypeCol = new string[100];//把词性辨析表的辨析字对应的type_col值填充此数组
    string[] ContentCol = new string[100];//把词性辨析表的辨析字对应的content_col值填充此数组
    string res = "";//截取的字符
    bool shima = true;//默认判断是动词

    //连接数据库
    string connectionString = @"Data Source=garden.db;Version=3;";
    SqliteConnection dbConnection;
    dbConnection = new SqliteConnection(connectionString);
    dbConnection.Open();

    //填充名词数组
    //第一步:sql指令
    //字符型变量要有引号,数字型变量不需要引号
    //word是变量,动态的,不能直接放到sql语句里面
    string sqlQuery = "select type_col,content_col from verb_judge where word_col = '" + word + "'";
    //第二步:执行指令
    SqliteCommand dbCommand;
    dbCommand = dbConnection.CreateCommand();
    dbCommand.CommandText = sqlQuery;
    dbCommand.ExecuteNonQuery();
    //第三步:填充词性辨析数组
    SqliteDataReader dbReader;
    dbReader = dbCommand.ExecuteReader();

    int i = 0;
    while (dbReader.Read())
    {
        //查询了2列(type_col和content_col),所以返回的结果集有2列,分别用GetValue(0)和GetValue(1)
        TypeCol[i] = dbReader.GetValue(0).ToString();//返回的结果集的第1列
        ContentCol[i] = dbReader.GetValue(1).ToString();//返回的结果集的第2列
        i++;//虽然定义数组长度为10,但i不一定填满了10
    }
    dbReader.Close();
    dbConnection.Close();
    
    if (i > 0)//在词性辨析表里找到内容了,否则i还是默认的0
    {
        for (int n = 0; n < i; n++)//遍历词性辨析表找到的各种结果
        {
            if (TypeCol[n] == "r1")//right1:右边1个字符
            {
                if (str.IndexOf(word) + word.Length + 1 <= str.Length)//要往右判断1个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 1);//截取动词右边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "r2")//right2:右边2个字符
            {
                if (str.IndexOf(word) + word.Length + 2 <= str.Length)//要往右判断2个字符,但不能超出数组界限
                {
                    res = str.Substring(str.IndexOf(word) + word.Length, 2);//截取动词右边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
            else if (TypeCol[n] == "l1")//left1:左边1个字符
            {
                if (str.IndexOf(word) - 1 >= 0)//要往左判断1个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 1, 1);//截取动词左边1个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }

                }
            }
            else if (TypeCol[n] == "l2")//left2:左边2个字符
            {
                if (str.IndexOf(word) - 2 >= 0)//要往左判断2个字符,但不能低于数组界限0
                {
                    res = str.Substring(str.IndexOf(word) - 2, 2);//截取动词左边2个字符
                    if (res == ContentCol[n])//截取的字符符合词性辨析表对应的字符
                    {
                        shima = false;//不是动词
                    }
                }
            }
        }
    }
    i = 0;
    return shima;
}

//判断句型
string SentenceJudge()
{
    /*
    基本单句有六种句型:
    只有性质状态(表语):真漂亮、对啊、太好了。句子里没有谓语动词,其余五种句型里,都有谓语动词。
    主语(动作执行者)-谓语(动作):张三摔倒。
    主语(动作执行者)-谓语(动作)-宾语(动作对象):猫吃鼠。
    主语-谓语(是)-表语(表明主语的身份和性质状态):张三是老师,太阳是美丽的。
    双宾语句型:主语(传输的人)-谓语(传输动作)-间接宾语(传输对象)-直接宾语(传输的事物):张三给李四苹果,张三教李四数学。
    宾语补足语句型:主语-谓语(例如把、使、让)-宾语-宾语补足语(做什么):张三让李四跳舞,张三把房间弄脏了。
    前面只说了主谓宾句型,还要处理其它句型。

    双宾语句型:
    双宾语句型的谓语动词后面有两个名词,例如张三给李四苹果,李四是间接宾语(名词),苹果是直接宾语(名词)。
    但是有两个名词的就是双宾语句型吗?不是的。例如张三喜欢足球学校。谓语动词后面有两个名词:足球、学校,但显然足球学校是一个整体名词,也就是主谓宾句型,而不是双宾语句型。因此判断双宾语句型,还要看谓语动词是不是适合双宾语句型的。
    双宾语句型的谓语动词主要是传输事物的动词:给、送给、教。
    那么谓语动词是双宾语句型的动词(例如给、教),且谓语动词后面有两个名词(体现为谓语动词右边的语句处理时,名词槽NounBox有两个名词,NounBox1和NounBox2都有值),就可以判断为双宾语句型。
    还有,像“足球学校”这样两个名词连在一起,就要合并成一个名词,作为主语或宾语。
    仅从双宾语句型的标志动词“教”判断双宾语句型,不一定准确,例如“他教我数学”是双宾语句型,但“他教书”就不是双宾语句型,所以还要根据宾语名词的数量,来判断到底是不是双宾语句型,如果动词右边只有一个名词,例如“他教书”的“书”,句子就不是双宾语句型。所以通过谓语动词判断一个句子是双宾语句型后,根据找到的名词数量,例如只有一个宾语名词,那么就要把双宾语句型,修正回主谓宾句型。
    名词次序:间接宾语在直接宾语之前,所以找到两个名词,次序在前面的那个名词,是间接宾语,次序在后面的那个名词是直接宾语。

    宾语补足语句型:
    和主谓宾句型不同,宾语补足语句型含有主谓宾句型的部分,但宾语后面还有个动作(动词),也就是宾语补足语。
    因此看宾语后面是否还有动词,是判断宾语补足语句型的方法。
    但是有两个动词就麻烦了,如何判断这个动词是谓语动词还是宾语补足语动词呢?那就需要先把所有动词找出来,如果是宾语补足语动词,那么这个动词在谓语动词的后面,如果是谓语动词,则在前面。
    既然要存放多个动词进行判断,就要有动词槽(VerbBox)。
    动词次序:谓语动词在宾语补足语动词之前,所以找到两个动词,词语次序在前面的是谓语动词,词语次序在后面的是宾语补足语动词。
    宾语补足语动词后面还有个名词,宾语补足语动词和这个名词合并在一起,作为宾语补足语。例如他让我打扫教室。如果宾语补足语只是“打扫”,话就说不清楚了。但是有些宾语补足语,就只有动词,后面没有名词,例如“他让我跳舞”就只有“跳舞”这一个动词,“跳舞”这个词后面没有名词,因为“跳舞”是不及物动词。

    双宾语句型和宾语补足语句型,都是由主谓宾句型拓展而成的。双宾语句型在主谓宾句型的基础上,多加了一个宾语。宾语补足语句型在主谓宾句型的基础上,多加了一个动词(宾语补足语)。所以先完成主谓宾句型,再根据是否有拓展,来判断是不是双宾语句型或宾语补足语句型。

    在主谓宾句型的基础上,如果没有宾语,就是主谓句型。如果没有主语,就是省略主语,例如对一个人喊“过来”,这句话的全句显然是“你过来”。
    */

    if (VerbBox1 == "")//没有动词
    {
        return "只有性质状态";//只有性质状态的句型
    }
    else if (VerbBox1 != "" && VerbBox2 == "")//有1个动词
    {
        if (VerbBox1 == "给" || VerbBox1 == "送" || VerbBox1 == "送给" || VerbBox1 == "教")//双宾语句型的常见动词(标志词)
        {
            return "双宾语";//双宾语句型
        }
        else
        {
            return "主谓宾";//主谓宾句型
        }
    }
    else if (VerbBox1 != "" && VerbBox2 != "")//有2个动词
    {
        return "宾语补足语";//宾语补足语句型
    }
    else
    {
        return "其它";
    }
}

//名词排序
void NounOrder()
{
    if (NounBox1 != "" && NounBox2 != "")//招到了2个名词,放在NounBox1和NounBox2
    {
        string temp = "";//临时变量
        if (dan.IndexOf(NounBox1) > dan.IndexOf(NounBox2))//如果NounBox1的名词在句子中的位置大于NounBox2的名词在句子中的位置
        {
            //交换位置,在句子中位置小的名词放前面,从而确保双宾语句型时,NounBox1放的是间接宾语,NounBox2放的是直接宾语,毕竟间接宾语在直接宾语前面
            temp = NounBox1;
            NounBox1 = NounBox2;
            NounBox2 = temp;
        }
        FindJianObject = NounBox1;
        FindZhiObject = NounBox2;
        //间接宾语和直接宾语的名词所有格,之后再做
    }
}

//名词结合成名词词组
void NounJoin()
{
    /*
    名词合并:例如“足球学校”这个词,会被当成两个名词“足球”和“学校”。但实际中,要把它们合并成一个组合名词,作为主语或宾语。
    前面说了判断两个字符之间的内容,如果两个字符(词语)是连续的,那么这两个词语之间的内容为空。
    示例:
    //截取两个指定字符之间的全部字符
    string str = "白色的猫嘲笑黑色的鼠";//全句
    string res = "";//结果
    string word1 = "的猫";
    string word2 = "的鼠";
    int Word1LastIndex = str.IndexOf(word1) + word1.Length;
    int Word2StartIndex = str.IndexOf(word2);
    res = str.Substring(Word1LastIndex, Word2StartIndex - Word1LastIndex);
    res = str.Substring(str.IndexOf(word1) + word1.Length, str.IndexOf(word2) - (str.IndexOf(word1) + word1.Length));//展开形式
    if (res == "")
    {
        UnityEngine.Debug.Log("连续");
    }
    else
    {
        UnityEngine.Debug.Log("不连续");
    }
    */
    
    string res;
    //判断NounBox1和NounBox2的名词是否需要合并
    if (NounBox1 != "" && NounBox2 != "")
    {
        res = "";
        //判断NounBox1和NounBox2之间是否有内容,如果没内容(res为空),就说明NounBox1和NounBox2是连续的名词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(NounBox1) + NounBox1.Length, dan.IndexOf(NounBox2) - (dan.IndexOf(NounBox1) + NounBox1.Length));
        if (res == "")
        {
            NounBox1 = NounBox1 + NounBox2;//名词合并
            NounBox2 = "";//合并后,置空
            if (NounBox3 != "")
            {
                NounBox2 = NounBox3;//填补置空的值,否则NounBox1有值,NounBox2为空,NounBox3又有值,就间隔了
                NounBox3 = "";//合并后,置空
                if (NounBox4 != "")
                {
                    NounBox3 = NounBox4;
                    NounBox4 = "";//合并后,置空
                }
            }
        }
    }

    /*
    //判断NounBox2和NounBox3的名词是否需要合并
    if (NounBox2 != "" && NounBox3 != "")
    {
        res = "";
        //判断NounBox2和NounBox3之间是否有内容,如果没内容(res为空),就说明NounBox2和NounBox3是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox2) + NounBox2.Length, dan.IndexOf(NounBox3) - (dan.IndexOf(NounBox2) + NounBox2.Length));
        if (res == "")
        {
            NounBox2 = NounBox2 + NounBox3;//名词合并
            NounBox3 = "";//合并后,置空
            if (NounBox4 != "")
            {
                NounBox3 = NounBox4;//填补置空的值
                NounBox4 = "";//合并后,置空
            }
        }
    }

    //判断NounBox3和NounBox4的名词是否需要合并
    if (NounBox3 != "" && NounBox4 != "")
    {
        res = "";
        //判断NounBox3和NounBox4之间是否有内容,如果没内容(res为空),就说明NounBox3和NounBox4是连续的名词,需要合并
        res = dan.Substring(dan.IndexOf(NounBox3) + NounBox3.Length, dan.IndexOf(NounBox4) - (dan.IndexOf(NounBox3) + NounBox3.Length));
        if (res == "")
        {
            NounBox3 = NounBox3 + NounBox4;//名词合并
            NounBox4 = "";//合并后,置空
        }
    }
    */
}

//动词排序
void VerbOrder()
{
    /*
    如果不排序会怎样?句子中找到的第一个动词,可能不是谓语动词,而是宾语补足语动词,以宾语补足语动词分割句子,就错了。
    谓语动词和宾语补足语动词,先找到哪个,取决于这两个词,谁在动词表前面排序,而动词的排序是不可知的,或许按笔划排序,或者按首字母排序
    */
    string temp = "";//临时变量
    if (VerbBox1 != "" && VerbBox2 != "")//招到了个动词,放在VerbBox1和VerbBox2
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox2))//如果VerbBox1的动词在句子中的位置大于VerbBox2的动词在句子中的位置
        {
            //交换位置,在句子中位置小动词的放前面,从而确保VerbBox1放的是谓语动词,而宾语补足语动词放到VerbBox2
            temp = VerbBox1;
            VerbBox1 = VerbBox2;
            VerbBox2 = temp;
        }

    }
    if (VerbBox3 != "")
    {
        if (dan.IndexOf(VerbBox1) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox1;
            VerbBox1 = VerbBox3;
            VerbBox3 = temp;
        }
        if (dan.IndexOf(VerbBox2) > dan.IndexOf(VerbBox3))
        {
            temp = VerbBox2;
            VerbBox2 = VerbBox3;
            VerbBox3 = temp;
        }
    }
    FindVerb = VerbBox1;
}

//动词结合成动词词组
void VerbJoin()
{
    //动词合并:例如“应该爱”是两个动词:情态动词“应该”和普通动词“爱”,应该合并成一个动词
    string res;
    //判断VerbBox1和VerbBox2的动词是否需要合并
    if (VerbBox1 != "" && VerbBox2 != "")
    {
        res = "";
        //判断VerbBox1和VerbBox2之间是否有内容,如果没内容(res为空),就说明VerbBox1和VerbBox2是连续的动词(中间没有字符间隔),需要合并
        res = dan.Substring(dan.IndexOf(VerbBox1) + VerbBox1.Length, dan.IndexOf(VerbBox2) - (dan.IndexOf(VerbBox1) + VerbBox1.Length));
        if (res == "")
        {
            VerbBox1 = VerbBox1 + VerbBox2;//名词合并
            FindVerb = VerbBox1;
            VerbBox2 = "";//合并后,置空
            if (VerbBox3 != "")
            {
                VerbBox2 = VerbBox3;//填补置空的值,否则VerbBox1有值,VerbBox2为空,VerbBox3又有值,就间隔了
                VerbBox3 = "";//合并后,置空
                if (VerbBox4 != "")
                {
                    VerbBox3 = VerbBox4;
                    VerbBox4 = "";//合并后,置空
                }
            }
        }
    }

}

//谓语动词的发生概率
void VerbRateJudge()
{
    /*
    动词前面是否有否定词,也很重要。
    例如“他爱猫”和“他不爱猫”,虽然谓语动词都是“爱”字,但前面加个“不”字,意义就相反了。所以看谓语动词前面是否有否定词,是很重要的事。
    谓语动词前面的否定词,一般有不、不要、不可以、不应该、不能、别。
    还有不确定肯定还是否定动词,例如“他不一定去”,“去”字是动词,但是动词前的“不一定”,并不像是“不”字那样对动词进行否定,而是对动词既不像是肯定,也不像是否定,而是不确定。
    因此对每句话的谓语动词,都要加一个性质:肯定、否定、不确定。
    但不确定,有时候偏向于肯定,例如“他可能去”。有时候不确定偏向于否定,例如“他不太可能去”以及“他或许不去”。
    那么动词发生概率分为五种:肯定、偏向肯定、不确定、偏向否定、否定。
    这其实就是在分析事情(谓语动词)发生的概率,这在概率分析上有用。
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 1, 1);
    指定词语左边1个字符:str.Substring(str.IndexOf(word) - 2, 1);
    */

    VerbRate = "肯定";//默认值:肯定
    string temp = "";//临时变量

    //先判断谓语动词左边的1个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不"))
    {
        VerbRate = "否定";
    }
    else if(temp.Contains("别"))
    {
        VerbRate = "否定";
    }

    //判断谓语动词左边的2个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不要"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不能"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("可能"))
    {
        VerbRate = "不确定";
    }
    else if (temp.Contains("或许"))
    {
        VerbRate = "不确定";
    }

    //判断谓语动词左边的3个字符,是否是否定词
    temp = dan.Substring(dan.IndexOf(FindVerb) - 1, 1);
    if (temp.Contains("不可以"))
    {
        VerbRate = "否定";
    }
    else if (temp.Contains("不应该"))
    {
        VerbRate = "否定";
    }
}

//找形容词
string SearchAdj(string str)
{
    string jieguo = "不包含";//默认值是不包含
    int m = adj.Length;//形容词数组的长度,也就是有多少个形容词
    string temp  = "";

    for (int n = 0; n < m; n++)
    {
        /*Contains函数用于判断包含关系,例如句子和形容词的包含关系
        就是用句子和形容词数组的形容词,一一比对,来判断是否包含形容词
        n的值从0逐渐增长到形容词数组的形容词数量值,这样数组也就经历了所有形容词
        */
        if (str.Contains(adj[n]))//包含
        {
            jieguo = "包含";
            temp = adj[n];
        }
    }

    if (jieguo == "包含")//找到了形容词
    {
        return temp;
    }
    else
    {
        return "";
    }
}

//找数词
void SearchNum(string str)
{
    //先确定数词单位
    int StrLength = str.Length;//全句长度
    string temp = "";
    string NumDanwei_type = "";//数字单位类型

    string[] shuzu_danwei_mignci = new string[] { "个", "名", "位", "只", "头", "匹", "条", "棵", "朵", "片", "根", "座", "栋", "台", "部", "本", "块", "件", "盏", "把", "所", "辆", "艘", "架", "扇", "间", "包", "盒", "袋", "箱", "桶", "双" };
    string[] shuzu_danwei_jiliang = new string[] { "米", "厘米", "毫米", "分米", "公里", "里", "微米", "纳米", "克", "斤", "公斤", "吨", "毫克", "升" };

    //字符串从右向左,每次读取一个字符进行处理
    for (int n = StrLength; n > 0; n--)
    {
        temp = str.Substring(n - 1, 1);//每次截取的一个字符,例如“年”字

        if (NumDanwei_type == "")
        {
            //名词单位数组
            foreach (string m in shuzu_danwei_mignci)//判断这个截取的字符是否在名词数组中
            {
                if (temp == m)//截取的字符属于名词数组(shuzu_danwei_mignci)中的字符,例如“个”字属于名词数组
                {
                    NumDanwei = m;
                    NumDanwei_type = "名词单位";
                    SearchNum2(str, NumDanwei, NumDanwei_type);

                    if (num_type == "汉字型数字")
                    {
                        FindNum = SearchNum3(FindNum);
                    }
                    break;
                }
            }
        }

        if (NumDanwei_type == "")
        {
            //计量数组
            foreach (string m in shuzu_danwei_jiliang)//判断这个截取的字符是否在计量数组中
            {
                if (temp == m)//截取的字符属于计量数组(shuzu_danwei_jiliang)中的字符,例如“米”字属于计量数组
                {
                    NumDanwei = m;
                    if (str.Contains("厘"))
                    {
                        NumDanwei = "厘" + NumDanwei;
                    }
                    else if (str.Contains("毫"))
                    {
                        NumDanwei = "毫" + NumDanwei;
                    }
                    else if (str.Contains("公"))
                    {
                        NumDanwei = "公" + NumDanwei;
                    }
                    NumDanwei_type = "计量单位";
                    SearchNum2(str, NumDanwei, NumDanwei_type);
                    if (num_type == "汉字型数字")
                    {
                        FindNum = SearchNum3(FindNum);
                    }
                    break;
                }
            }
        }
    }

    /*
    找数字的其它方法:正则表达式。
    需要using System.Text.RegularExpressions;//正则表达式找出数字所需
    replace函数把不是数字的部分变为空无,这样就只剩下数字部分。
    string res = "";
    res = Regex.Replace(str, @"[^0-9]+", "");
    return res;
    */
}

void SearchNum2(string str, string temp, string NumDanwei_type)
{
    //找数字
    string[] shuzu_num = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
    string[] shuzu_num_cn = new string[] { "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "零", "十", "百", "千", "万" };

    //数量单位字符左边的字符串
    string WordLeft = str.Substring(0, str.IndexOf(temp));//例如“有6米”的“有6”

    //找阿拉伯数字,例如1、2、3这类数字
    //逐一处理该字符左边的每个字符
    int WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
    string temp2 = "";
    //从右向左,逐字截取
    for (int j = WordleftLength; j > 0; j--)
    {
        temp2 = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
                                             //从右到左,遇到不是数字的时候,就退出循环
        if (temp2 != "1" && temp2 != "2" && temp2 != "3" && temp2 != "4" && temp2 != "5" && temp2 != "6" && temp2 != "7" && temp2 != "8" && temp2 != "9" && temp2 != "0")
        {
            break;
        }
        foreach (string m2 in shuzu_num)//判断这个截取的字符是否在数字数组中
        {
            if (temp2 == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
            {
                if (NumDanwei_type == "名词单位" || NumDanwei_type == "计量单位")
                {
                    //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                    if (FindNum == "")
                    {
                        FindNum = temp2;
                    }
                    else
                    {
                        FindNum = temp2 + FindNum;
                    }
                    num_type = "阿拉伯数字";
                }
            }
        }
    }

    if (NumDanwei_type == "名词单位" || NumDanwei_type == "计量单位")
    {
        if (FindNum == "")//没有找到阿拉伯数字
        {
            //找汉字型数字,例如一、二、三
            WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
            temp2 = "";
            //从右向左,逐字截取
            for (int j = WordleftLength; j > 0; j--)
            {
                temp2 = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
                foreach (string m2 in shuzu_num_cn)//判断这个截取的字符是否在数字数组中
                {
                    if (temp2 == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
                    {
                        //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                        if (FindNum == "")
                        {
                            FindNum = temp2;
                        }
                        else
                        {
                            FindNum = temp2 + FindNum;
                        }
                        num_type = "汉字型数字";
                    }
                }
            }
        }
    }
}

string SearchNum3(string find_num)
{
    //汉字型数字转化为阿拉伯数字,例如“二十”转化为“20”
    //这个转化有时候不准确
    int old = 1;
    int result = 0;
    string temp = "";
    int temp_num = 0;

    //old(上一位数字)需要初始化为1,不能初始化为0,也不能不赋值
    //因为如果数字开始(从左到右)第一个字符就是翻倍数(例如十),那么翻倍的上一位数(old)不能默认0或NULL
    //如果翻倍数没有上一位数,拿默认1当上一位数(old初始化为1),翻倍数乘以1,就等于翻倍数翻倍自身,这样才正确

    for (int n = 1; n <= find_num.Length; n++)
    {
        temp = find_num.Substring(n - 1, 1);//每次截取的一个字符
        switch (temp)
        {
            case "一":
                temp_num = 1;
                break;
            case "二":
                temp_num = 2;
                break;
            case "两":
                temp_num = 2;
                break;
            case "三":
                temp_num = 3;
                break;
            case "四":
                temp_num = 4;
                break;
            case "五":
                temp_num = 5;
                break;
            case "六":
                temp_num = 6;
                break;
            case "七":
                temp_num = 7;
                break;
            case "八":
                temp_num = 8;
                break;
            case "九":
                temp_num = 9;
                break;
            case "零":
                temp_num = 0;
                break;
            case "十":
                temp_num = 10;
                break;
            case "百":
                temp_num = 100;
                break;
            case "千":
                temp_num = 1000;
                break;
            case "万":
                temp_num = 10000;
                break;
            default:
                break;
        }

        if (temp_num != 10 && temp_num != 100 && temp_num != 1000 && temp_num != 10000)//不是翻倍字符(十、百、千、万),而是0到9的数字
        {
            old = temp_num;//把数字存起来,下一次循环时,被下一位翻倍数所翻倍
            if (n == find_num.Length)//当i的长度等于总数字的长度,也就是到了最后一位数(个位数),不用翻倍了
            {
                result = result + temp_num;//个位数不用翻倍,直接加
            }
        }
        else//不是0到9的数字字符,而是翻倍字符,就要翻倍
        {
            //翻倍对象是上一位数字,就是old里存的数字。因为这次循环走else路线,所以temp_num没有赋值给old,因此old里还是上一位的数字
            result = result + (old * temp_num);//此时的temp_num是翻倍单位(十、百、千、万),不是0到9的数字,翻倍上一位数字(old)
        }
    }

    if (result != 0)
    {
        find_num = result.ToString();
        return find_num;
    }
    else
    {
        return "";
    }
}

//找时间(文字形式)
void SearchTime1(string str)
{
    string[] shuzu_danwei_time1 = new string[] { "今天", "明天", "后天", "昨天", "前天", "这个月", "下个月", "上个月", "今年", "明年", "去年" };
    string[] shuzu_danwei_time2 = new string[] { "早晨", "上午", "中午", "下午", "傍晚", "晚上", "傍晚", "夜晚", "半夜", "黎明", "黄昏", "清晨" };
    string[] shuzu_danwei_time3 = new string[] { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日", "礼拜一", "礼拜二", "礼拜三", "礼拜四", "礼拜五", "礼拜六", "礼拜天" };
    string[] shuzu_danwei_time4 = new string[] { "春天", "夏天", "秋天", "冬天", "春季", "夏季", "秋季", "冬季" };
    string[] shuzu_danwei_time5 = new string[] { "元旦", "大年三十", "除夕", "春节", "大年初一", "大年初二", "大年初三", "正月十五", "寒假", "清明节", "五一节", "劳动节", "儿童节", "暑假", "中秋节", "国庆节", "圣诞节", "假期", "休息日" };

    foreach (string m in shuzu_danwei_time1)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time2)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time3)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time4)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }

    foreach (string m in shuzu_danwei_time5)
    {
        if (str.Contains(m))
        {
            FindTime2 = m;
        }
    }
}

//找时间(年月日时分,布置框架)
void SearchTime2(string str)
{
    //找年月日时分
    string TimeDanwei = "";

    if (str.Contains("年"))
    {
        TimeDanwei = "年";
        FindTime_year = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("月"))
    {
        TimeDanwei = "月";
        FindTime_month = SearchTime3(str, TimeDanwei);
        if (num_type == "汉字型数字")
        {
            FindTime_month = SearchNum3(FindTime_month);
        }
    }
    if (str.Contains("日"))
    {
        TimeDanwei = "日";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("点"))
    {
        TimeDanwei = "点";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
    if (str.Contains("分"))
    {
        TimeDanwei = "分";
        FindTime_day = SearchTime3(str, TimeDanwei);
    }
}

//找时间(年月日时分,具体找)
string SearchTime3(string str, string TimeDanwei)
{
    //找数字
    string num = "";
    string[] shuzu_num = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
    string[] shuzu_num_cn = new string[] { "一", "二", "两", "三", "四", "五", "六", "七", "八", "九", "零", "十", "百", "千", "万" };

    //数量单位字符左边的字符串
    string WordLeft = str.Substring(0, str.IndexOf(TimeDanwei));
    //找阿拉伯数字,例如1、2、3这类数字
    //逐一处理该字符左边的每个字符
    int WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
    string temp = "";
    //从右向左,逐字截取
    for (int j = WordleftLength; j > 0; j--)
    {
        temp = WordLeft.Substring(j - 1, 1);//每次截取的一个字符

        //从右到左,遇到不是数字的时候,就退出循环
        if (temp != "1" && temp != "2" && temp != "3" && temp != "4" && temp != "5" && temp != "6" && temp != "7" && temp != "8" && temp != "9" && temp != "0")
        {
            break;
        }

        foreach (string m in shuzu_num)//判断这个截取的字符是否在数字数组中
        {
            if (temp == m)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
            {
                //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                if (num == "")
                {
                    num = temp;
                }
                else
                {
                    num = temp + num;
                }
                num_type = "阿拉伯数字";

            }
        }
    }

    if (num == "")//没有找到阿拉伯数字
    {
        //找汉字型数字,例如一、二、三
        WordleftLength = WordLeft.Length;//例如“有6”这个字符串的长度
        temp = "";
        //从右向左,逐字截取
        for (int j = WordleftLength; j > 0; j--)
        {
            temp = WordLeft.Substring(j - 1, 1);//每次截取的一个字符
            foreach (string m2 in shuzu_num_cn)//判断这个截取的字符是否在数字数组中
            {
                if (temp == m2)//截取的字符属于数字数组(shuzu_num)中的字符,例如“1”字属于数字数组
                {
                    //现在找出来的都是数字,但是都是倒序,需要拼接在一起
                    if (num == "")
                    {
                        num = temp;
                    }
                    else
                    {
                        num = temp + num;
                    }
                    num_type = "汉字型数字";
                }
            }
        }
    }

    if (num != "")
    {
        return num;
    }
    else
    {
        return "";
    }

}

//地点
bool difang(string str, string word)
{
    if (str.IndexOf(word) > 0)
    {
        string temp = str.Substring(str.IndexOf(word) - 1, 1);
        if (temp == "在" || temp == "到" || temp == "去" || temp == "来")
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

//显示最终输出结果
void ShowResult()
{
    UnityEngine.Debug.Log("第" + dan_num + "句:" + danju[dan_num-1]);
    UnityEngine.Debug.Log("句型:" + SentenceType);

    if (SentenceType == "主谓宾")//主谓宾句型
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("语态:" + yutai);
    }
    else if (SentenceType == "双宾语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("间接宾语:" + FindJianObject);
        UnityEngine.Debug.Log("直接宾语:" + FindZhiObject);
    }
    else if (SentenceType == "宾语补足语")
    {
        UnityEngine.Debug.Log("主语:" + FindSubject);
        UnityEngine.Debug.Log("谓语:" + FindVerb);
        UnityEngine.Debug.Log("宾语:" + FindObject);
        UnityEngine.Debug.Log("宾语补足语动词:" + FindBuVerb);
        UnityEngine.Debug.Log("宾语补足语名词:" + FindBuNoun);
    }
    else if (SentenceType == "只有性质状态")
    {
        UnityEngine.Debug.Log("只有性质状态:" + dan);
    }

    UnityEngine.Debug.Log("动词发生概率:" + VerbRate);

    //显示名词所有格
    if (SubjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("主语的名词所有格:" + SubjectSuoyouge);
    }
    if (ObjectSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语的名词所有格:" + ObjectSuoyouge);
    }
    if (JianSuoyouge != "")
    {
        UnityEngine.Debug.Log("间接宾语的名词所有格:" + JianSuoyouge);
    }
    if (ZhiSuoyouge != "")
    {
        UnityEngine.Debug.Log("直接宾语的名词所有格:" + ZhiSuoyouge);
    }
    if (BuSuoyouge != "")
    {
        UnityEngine.Debug.Log("宾语补足语的名词所有格:" + BuSuoyouge);
    }

    //显示形容词
    if (SubjectAdj != "")
    {
        UnityEngine.Debug.Log("主语的形容词:" + SubjectAdj);
    }
    if (ObjectAdj != "")
    {
        UnityEngine.Debug.Log("宾语的形容词:" + ObjectAdj);
    }
    if (JianAdj != "")
    {
        UnityEngine.Debug.Log("间接宾语的形容词:" + JianAdj);
    }
    if (ZhiAdj != "")
    {
        UnityEngine.Debug.Log("直接宾语的形容词:" + ZhiAdj);
    }
    if (BuAdj != "")
    {
        UnityEngine.Debug.Log("宾语补足语的形容词:" + BuAdj);
    }

    //显示数词
    if (SubjectNum != "")
    {
        UnityEngine.Debug.Log("主语的数词:" + SubjectNum);
    }
    if (ObjectNum != "")
    {
        UnityEngine.Debug.Log("宾语的数词:" + ObjectNum);
    }
    if (JianNum != "")
    {
        UnityEngine.Debug.Log("间接宾语的数词:" + JianNum);
    }
    if (ZhiNum != "")
    {
        UnityEngine.Debug.Log("直接宾语的数词:" + ZhiNum);
    }
    if (BuNum != "")
    {
        UnityEngine.Debug.Log("宾语补足语的数词:" + BuNum);
    }

    //显示时间
    if (FindTime_year != "")
    {
        UnityEngine.Debug.Log("年:" + FindTime_year);
    }
    if (FindTime_month != "")
    {
        UnityEngine.Debug.Log("月:" + FindTime_month);
    }
    if (FindTime_day != "")
    {
        UnityEngine.Debug.Log("日:" + FindTime_day);
    }
    if (FindTime_hour != "")
    {
        UnityEngine.Debug.Log("时(几点):" + FindTime_hour);
    }
    if (FindTime_minute != "")
    {
        UnityEngine.Debug.Log("分(几分):" + FindTime_minute);
    }
    if (FindTime2 != "")
    {
        UnityEngine.Debug.Log("时间:" + FindTime2);
    }

    //显示地点
    if (didian != "")
    {
        UnityEngine.Debug.Log("地点:" + didian);
    }

    GuessWord();//猜测词语

    //tmpText.text = mes;

    //清空变量
    FindSubject = "";
    FindVerb = "";
    FindObject = "";
    FindBuVerb = "";
    FindBuNoun = "";
    FindJianObject = "";
    FindZhiObject = "";

    yutai = "";

    SubjectSuoyouge = "";
    ObjectSuoyouge = "";
    JianSuoyouge = "";
    ZhiSuoyouge = "";
    BuSuoyouge = "";

    SubjectAdj = "";
    ObjectAdj = "";
    JianAdj = "";
    ZhiAdj = "";
    BuAdj = "";

    SubjectNum = "";
    ObjectNum = "";
    JianNum = "";
    ZhiNum = "";
    BuNum = "";
}

//猜测词语
void GuessWord()
{
    /*
    不建议用猜测词语,因为如果一个词语,词库里没有,要靠程序猜测,那么游戏剧情肯定对这个词语没做任何准备,就算猜测出这个词,也没用。
    例如张三爱雅娜,名词词库肯定没有“雅娜”这个词,但是谓语动词“爱”字右边的句子的两个字,显然是宾语名词,所以猜测词语是很容易猜测的。
    就算猜测出宾语是雅娜,又怎样了呢,对雅娜的信息和属性,什么都没有设置,程序没法分析。甚至连雅娜到底是一个人还是一块石头,都没法分析。
    那么张三带着雅娜去海边,到底是张三带着女人雅娜去海边,还是张三带着石头雅娜去海边,准备扔石头玩水漂。计算机分析程序一头雾水,所以猜测词语会降低计算机的分析能力。
    还是勤快点吧,把词语录入词库,并给词语设置信息和属性。什么时候用猜测词语呢?词库词汇量还不够多的时候,只能靠猜词来补偿,但这不是长远的办法。
    这就好比编程强调“对变量,要先定义,后使用”,猜测词语就好比不定义就直接使用。

    猜测词语的原理:抽取掉已知的词语(词库里有的词语),剩下的未知的词语(词库里没有的词语),就是要猜测的词。
    例如“张三喜欢美丽的雅娜”,谓语动词右边句是“美丽的雅娜”,词库已有的形容词是“美丽的”,抽取掉形容词“美丽的”,剩下的词语“雅娜”就是要猜测的宾语。
    */

    string GuessObject = "";//猜测宾语
    string GuessBuNoun = "";//猜测宾语补足语的名词
    string GuessJian = "";//猜测间接宾语
    string GuessZhi = "";//猜测直接宾语
    string temp = "";//临时变量

    //猜测主谓宾句型的宾语
    if (SentenceType == "主谓宾")
    {
        if (FindObject == "")
        {
            temp = RightPart;//谓语动词右边句
            if (ObjectSuoyouge != "")
            {
                temp = RightPart.Replace("ObjectSuoyouge", "");//把名词所有格变为空无,就是抽取掉
            }
            if (ObjectAdj != "")
            {
                temp = RightPart.Replace("ObjectAdj", "");//把形容词变为空无,就是抽取掉
            }
            if (ObjectNum != "")
            {
                temp = RightPart.Replace("ObjectNum", "");//把数词变为空无,就是抽取掉
            }
            if (temp != "")
            {
                GuessObject = temp;
            }
        }
    }

    //宾语补足语句型,猜测名词
    //谓语动词和宾语补足语名词之间的字符串,就是要猜测的宾语名词
    if (SentenceType == "宾语补足语")
    {
        if (FindObject == "")
        {
            temp = dan;
            temp = dan.Substring(dan.IndexOf(FindVerb) + FindVerb.Length, dan.IndexOf(FindVerb) - (dan.IndexOf(FindVerb) + FindVerb.Length));
            GuessObject = temp;
        }
        //宾语补足语句型,猜测宾语补足语名词
        if (FindBuNoun == "")
        {
            temp = "";
            temp = dan.Substring(dan.IndexOf(FindBuVerb) + FindBuVerb.Length, dan.Length - (dan.IndexOf(FindBuVerb) + FindBuVerb.Length));
            if (temp != "")
            {
                GuessBuNoun = temp;
            }
        }
    }

    /*
    猜测双宾语句型的直接宾语。
    例如“张三给李四一个雅娜”,李四是间接宾语,也是词库已有的名词,雅娜是直接宾语,词库没有这个名词,只能靠猜测词语。
    间接宾语和直接宾语之间,有一个定语(数词:一个),这个定语右边的词语,就是直接宾语,左边的名词就是间接宾语。
    前面的程序里,如果双宾语句型,只找到一个宾语名词(直接宾语或间接宾语),那就转化为主谓宾句型了,因为主谓宾句型只有一个宾语。但实际上可能是双宾语句型中,有个宾语不属于词库,所以没找到。
    如果谓语动词是给、给予,这是双宾语句型的标志动词,确实很可能是双宾语句型,那么就当双宾语句型去猜词吧。
    */

    //猜测主谓宾句型的宾语
    if (SentenceType == "主谓宾")//假如之前把双宾语句型误当主谓宾句型
    {
        if (FindVerb == "给" || FindVerb == "给予" || FindVerb == "送给" || FindVerb == "教")//双宾语句的标志动词
        {
            if (ObjectAdj != "")
            {
                //谓语动词右边句里,宾语形容词(ObjectAdj)的左边句
                string temp_left = RightPart.Substring(0, RightPart.IndexOf(ObjectAdj));
                //谓语动词右边句里,宾语形容词(ObjectAdj)的右边句
                string temp_right = RightPart.Substring(RightPart.IndexOf(ObjectAdj) + ObjectAdj.Length, RightPart.Length - (RightPart.IndexOf(ObjectAdj) + ObjectAdj.Length));
                if (temp_left != "")
                {
                    GuessJian = temp_left;
                }
                if (temp_right != "")
                {
                    GuessZhi = temp_right;
                }
            }
            if (ObjectNum != "")
            {
                //谓语动词右边句里,宾语数词(ObjectNum)的左边句
                string temp_left = RightPart.Substring(0, RightPart.IndexOf(ObjectNum));
                //谓语动词右边句里,宾语数词(ObjectNum)的右边句
                string temp_right = RightPart.Substring(RightPart.IndexOf(ObjectNum) + ObjectNum.Length, RightPart.Length - (RightPart.IndexOf(ObjectNum) + ObjectNum.Length));
                if (temp_left != "")
                {
                    GuessJian = temp_left;
                }
                if (temp_right != "")
                {
                    GuessZhi = temp_right;
                }
            }
            if (ObjectSuoyouge != "")
            {
                //谓语动词右边句里,宾语的名词所有格(ObjectSuoyouge)的左边句
                string temp_left = RightPart.Substring(0, RightPart.IndexOf(ObjectSuoyouge));
                //谓语动词右边句里,宾语的名词所有格(ObjectSuoyouge)的右边句
                string temp_right = RightPart.Substring(RightPart.IndexOf(ObjectSuoyouge) + ObjectSuoyouge.Length, RightPart.Length - (RightPart.IndexOf(ObjectSuoyouge) + ObjectSuoyouge.Length));
                if (temp_left != "")
                {
                    GuessJian = temp_left;
                }
                if (temp_right != "")
                {
                    GuessZhi = temp_right;
                }
            }
        }
    }

    //显示结果
    if (GuessObject != "")
    {
        UnityEngine.Debug.Log("猜测宾语:" + GuessObject);
    }
    if (GuessBuNoun != "")
    {
        UnityEngine.Debug.Log("猜测宾语补足语的名词:" + GuessBuNoun);
    }
    if (GuessJian != "")
    {
        UnityEngine.Debug.Log("猜测间接宾语:" + GuessJian);
    }
    if (GuessZhi != "")
    {
        UnityEngine.Debug.Log("猜测直接宾语:" + GuessZhi);
    }

    //清空变量
    GuessObject = "";
    GuessBuNoun = "";
    GuessJian = "";
    GuessZhi = "";
}

}

热门相关:黄金万两粤语   妻子的绝地反攻   让姐姐迈出一步的妻子