《機器人技術》第一次作業
題目: 在機器人足球比賽中,server和球員client之間通過發送字符串來進行信息交互,其中server要把某球員的聽覺和視覺信息發送給該球員,信息的格式如下所示:
(hear Time Sender Message)
(see Time ObjInfo ObjInfo …)
其中
(hear Time Sender Message)的具體含義如下:
- Time:前的仿真周期。
- Sender
- 如果是其他球員發送的消息,那么是發送者的相當方向(Direction)
- self:發送者是自己本人。
- referee:裁判是發送者。
- online_coach_left 或者online_coach_ringt:發送者是在線教練。
- Message:消息內容。
(see Time ObjInfo ObjInfo …)的具體含義如下:
- Time:當前時間。
- ObjInfo表示了可視對象的信息。其格式為:
(ObjName Distance Direction DistChng DirChng BodyDir HeadDir)
¡ ObjName = (player Teamname Unum)
- |(goal Side)
- |(ball)
- |(flag c)
- |(flag [ l | c | r] [ t | b ])
- |(flag p [ l | r] [ t | c | b ])
- |(flag [ t | b] [ l | r ] [10 | 20 | 30 | 40 |50 ])
- |(flag [ l | r] [ t | b ] [10 | 20 | 30 ])
- |(flag [ l | r | t | b ] 0)
- |(line [ l | r | t | b ])
¡ Distance,Direction表示目標的相對距離和相對方向
¡ DistChng和DirChng分別表示目標距離和方向的相對變化,如果是固定物體(球和球員以外的所有對象)則沒有改項值
¡ BodyDir 和HeadDir,分別是被觀察球員相對觀察者的身體和頭部的相對角度,只有是球隊對象才有這一項值。
要求:編寫程序解析球員所看到和聽到的信息。
示例:(hear 1022 -30 passto(23,24))(see 1022 ((ball) 20 -20 1 -2) ((player hfut1 2) 23 45 0.5 1 22 40 ) ((goal r) 12 20))
輸出:
在1022周期 hear 從 -30 方向 聽到了 passto(23,24);
在1022周期 see Ball 距離我的 Distance 是 20, Direction是 -20,DistChng是1,DirChng是-2;player hfut 2距離我的Distance 是 23, Direction是 45,DistChng是0.5,DirChng是1,它的BodyDir是 22和HeadDir 是 44;goal r 距離我的Distance 是 12, Direction是 20。
一些參考建議:
場上對象: (f r b 10)表示場上某個點,具體見教材28頁,教材上寫的是(flag r b 10),大家寫程序的時候以f為准。
本示例中左右2邊的名稱分別為hfut1和hfut2, 大家寫程序的時候hfut1的球員信息存儲在在隊友里面,hfut2存儲在對手里面。
Java源碼:
就是對字符串的簡單解析。
package RobatHomework1;
public class Getmessage {
public static void main(String args[]) {
String text = "(hear 1022 -30 passto(23,24)) (see 1022 ((ball) 20 -20 1 -2) ((player hfut1 2) 23 45 0.5 1 22 40 ) ((goal r) 12 20))";
String text2 = "(hear 8888 referee 好球!)(see 8888 ((ball) 121 -210.1 12 -22) ((player hfut1 5) 223 445 0.15 1 22 40 ) ((goal r) 12 20) ((f r b 10) 23 45))";
String text3 = "(hear 1022 -30 passto(23,24))(see 1022 ((ball) 20 -20 1 -2) ((player hfut1 2) 23 45 0.5 1 22 40 ) ((g r) 12 20))";
String text4 = "(hear 2021 self \"I'm numb5\")(see 0 ((g r) 64.1 13) ((f r t) 64.5 -16) ((f r b) 79 38) ((f p r t) 46.1 -6) ((f p r c) 48.1 18) ((f p r b) 58 37) ((l r ) 62.8 -89))";
String text5 = "(hear 1024 referee corner_kick_r)(see 0 ((g r) 64.1 13) ((f r t) 64.5 -16) ((f r b) 79 38) ((f p r t) 46.1 -6) ((f p r c) 48.1 18) ((f p r b) 58 37) ((l r ) 62.8 -89))";
Parting a = new Parting();
Parting b = new Parting();
Parting c = new Parting();
Parting d = new Parting();
Parting e = new Parting();
System.out.println("測試數據1:");
a.GetHS(text);
// 測試System.out.println(a.HearMessage);
// 測試System.out.println(a.SeeMessage);
a.ReturnHear();
a.ReturnSee();
System.out.println("測試數據2:");
b.GetHS(text2);
b.ReturnHear();
b.ReturnSee();
System.out.println("測試數據3:");
c.GetHS(text3);
c.ReturnHear();
c.ReturnSee();
System.out.println("測試數據4:");
d.GetHS(text4);
d.ReturnHear();
d.ReturnSee();
System.out.println("測試數據5:");
e.GetHS(text5);
e.ReturnHear();
e.ReturnSee();
}
}
class Parting {
String HearMessage;
String SeeMessage;
// 初步獲取信息,將信息分割成hear和see兩塊
void GetHS(String MyMessage) {
this.HearMessage = MyMessage.substring(MyMessage.indexOf("hear") - 1, MyMessage.indexOf("see") - 1);
this.SeeMessage = MyMessage.substring(MyMessage.indexOf("see") - 1, MyMessage.length());
this.HearMessage.trim();
this.SeeMessage.trim();
}
//解析hear內容
void ReturnHear() {
String[] hemes;
// 去除無關信息,將聽到的內容格式化,使其以括號組形式存在
String Hearme = this.HearMessage.substring(this.HearMessage.indexOf("(") + 1,
this.HearMessage.lastIndexOf(")"));
// 用空格進行分割 因為經過上面的處理,剩余的信息是() () () 這樣括號組以空格分割的形式
hemes = Hearme.split(" ");
/*
* 測試 for(int i =0;i<=3;i++){ System.out.println(hemes[i]); }
*/
Boolean strResult = hemes[2].matches("-?[0-9]+.?[0-9]*"); // 正則表達式,判斷是否是數字
// 如果是數字就需要加方向
if (strResult == true) {
System.out.print("在" + hemes[1] + "周期 hear從" + hemes[2] + "方向聽到了");
for (int i = 3; i < hemes.length; i++) {
System.out.print(hemes[i] + " ");
}
System.out.println();
} else {
System.out.print("在" + hemes[1] + "周期 hear從" + hemes[2] + "聽到了");
for (int i = 3; i < hemes.length; i++) {
System.out.print(hemes[i] + " ");
}
System.out.println();
}
}
//對看見的信息進行處理
void ReturnSee() {
// 去除無關信息,留下以括號組存在的格式化信息
String temp = this.SeeMessage.substring(this.SeeMessage.indexOf("(", 2), this.SeeMessage.lastIndexOf(")"));
temp.trim();// 去空格
// System.out.println(temp);
String time1 = this.SeeMessage.substring(5, this.SeeMessage.indexOf("(", 2) - 1);
time1.trim();
// System.out.println(time1);
String messages[] = new String[20];
int count = 0, begin = 0, end = 0, count1 = 0;
// 看到了多個信息,每個信息以括號組形式存在,下面提取出來
for (int i = 0; i < temp.length(); i++) {
if (count == 0) {
begin = i;
}
if (temp.charAt(i) == '(') {
count++;
}
if (temp.charAt(i) == ')') {
count--;
if (count == 0) {
end = i + 1;
messages[count1] = temp.substring(begin, end);
count1++;
}
}
}
System.out.print("在" + time1 + "周期see ");
for (int j = 0; j < count1; j++) {
// System.out.println(messages[j]);
// 下面確認信息源,因為球 球員以及固定物的格式化信息是不同的,需要分別處理
if (messages[j].contains("player")) {
// 下面是提取信息源名稱后面的信息,並分割。
String[] playermessage = (messages[j]
.subSequence(messages[j].indexOf(')') + 1, messages[j].lastIndexOf(')')).toString().trim())
.split(" ");
/*
* int k = 0; for(k=0;k<playermessage.length;k++) {
* System.out.println(playermessage[k]);
*
* }
*/
System.out.println(
messages[j].substring(2, messages[j].indexOf(')')) + " 距離我的 Distance 是" + playermessage[0]
+ ",Direction是 " + playermessage[1] + ",DistChng是" + playermessage[2] + ",DirChng是"
+ playermessage[3] + ",它的BodyDir是" + playermessage[4] + "和HeadDir是" + playermessage[5]);
} else if (messages[j].contains("ball")) {
String[] ballmessage = (messages[j]
.subSequence(messages[j].indexOf(')') + 1, messages[j].lastIndexOf(')')).toString().trim())
.split(" ");
/*
* int k = 0;
*
* for(k=0;k<ballmessage.length;k++) { System.out.println(ballmessage[k]); }
*/
System.out.println(messages[j].substring(2, messages[j].indexOf(')')) + " 距離我的 Distance 是"
+ ballmessage[0] + ",Direction是 " + ballmessage[1] + ",DistChng是" + ballmessage[2] + ",DirChng是"
+ ballmessage[3]);
} else {
String[] Fixturemessage = (messages[j]
.subSequence(messages[j].indexOf(')') + 1, messages[j].lastIndexOf(')')).toString().trim())
.split(" ");
/*
* int k = 0; for(k=0;k<Fixturemessage.length;k++) {
* System.out.println(Fixturemessage[k]); }
*/
System.out.println(messages[j].substring(2, messages[j].indexOf(')')) + " 距離我的 Distance 是"
+ Fixturemessage[0] + ",Direction是 " + Fixturemessage[1]);
}
}
}
}
運行效果:
注:第一、三、四、五組為課本或作業舉例信息,第二組為自行虛擬信息,均能成功解析,解析的hear數據各自儲存在hemes數組,解析see的數據各自儲存messages數組中,非常易於重新提取或賦值給其他對象。