南昌航空大學實驗報告
2021 年 11 月 12 日
課程名稱:面向對象程序設計B 實驗名稱: 農夫過河之繼承與多態
學號: 姓名: 同組人:
指導教師評定: 簽名:
一、實驗目的
1、 掌握Java語言中多態的基本概念及使用方法;
2、 掌握上轉型和下轉型的基本概念及使用方法;
3、 掌握Object類中的toString()、equals()的使用方法;
4、 掌握instanceOf運算符的使用方法;
5、 掌握Java語言中成員變量隱藏的基本概念及使用方法;
二、實驗要求
1、 根據實驗步驟中提出的要求,使用eclipse等開發工具編寫相應的Java程序;
2、 編譯、運行自己所編寫的Java程序;
3、 根據編譯與運行過程中所獲得的錯誤信息修改程序直至獲得正確的結果;
4、 記錄實驗中遇到的各類問題並以及解決辦法。
三、實驗步驟
實驗三(1)實驗步驟
1、 農夫過河問題:將之前的代碼進行如下改進:
(1) 為之前的類添加合適的父類。
(2) 為父類添加適合的屬性和方法。並以此為基礎修改原有的類,使之與添加的類構成繼承關系。
(3) 使用多態改進整個代碼,提高代碼的復用性。
如附錄中的代碼所示,添加了object作為農夫,羊,狼,白菜的父類,具體的請看第二步的類圖。
2、 請畫出完整類圖,包含每個類的類名、屬性、方法以及類與類的關聯,並用文字說明關聯類的關聯關系。
類圖如下:
3、 說明你設計的繼承關系的理由,為什么不用組合
因為setcrossriver()方法,eat()方法,sethascross()方法都能用到,並且繼承和組合都是面向對象中代碼復用的方式,父類的內部細節對子類可見,但是在組合當中,對象之間的內部細節不可見。更重要的是繼承強調的是is-a的關系,組合強調的是has-a的關系。在這里我覺得繼承更為恰當。
實驗三(2)實驗步驟
4、 農夫過河問題,將之前的代碼進行如下改進:
(1) 修改程序代碼,在游戲中增加胡蘿卜、兔子兩個角色,過河的規則改為一次可以帶兩樣東西過河。
具體改進請看代碼。代碼在附錄。
5、 請畫出完整類圖,包含每個類的類名、屬性、方法以及類與類的關聯,並用文字說明關聯類的關聯關系
Object是抽象類作為父類,里面的方法有是否過河,是否存活,是否上船,以及判斷是否吃的方法。
而rabbit,wolf,farmer,carrot,cabbage則作為子類繼承父類的方法與屬性。
GameGui是界面類,Game是游戲具體執行類
這兩個類大體和之前一樣無變動。
6、 實現第一步的功能時,你的代碼做了哪些修改。如何避免修改原有代碼?
首先是增加了carrot類和rabbit類,同時改動了界面的顯示,也就是GameGui類進行改動增加了幾個顯示。也改變了wolf類和sheep類里面eat這各方法,都增加了一種可被吃食物的判斷。最后則是對Game類這個游戲具體執行的地方加上rabbit和carrot行動方式。
如何避免代碼的修改:主要還是要看類是如和划分的,它們的耦合性如何,關聯性強不強,像我的代碼整體耦合性還是比較低的改動起來還是蠻方便的,改動的話大部分都是添加類和添加方法,改動方面就改動了兩個極小的地方(也就是eat方法里面多了一個選擇判斷)。
7、 修改系統功能,運行程序后,用戶可以選擇玩新規則(五個角色、一次兩樣東西帶過河)或者老規則(三個角色、一次一樣東西帶過河)的游戲。
具體實現看代碼。代碼在附錄。
四、實驗結果
運行結果如下:
選擇模式(滿足實驗要求1和4):
若選1:(在這里就給出成功和失敗的截圖)
失敗;
成功:
若選2:
失敗:
成功:
五、實驗小結
這個實驗是分為兩個課時的,第一節課是完成將以前的農夫過河問題用到繼承來實現,第二節課則是添加了兩個新類同時游戲規則也稍稍改變,整體實驗說不上難,主要就是看考慮的周到不周到,我新增了兩個子類后最開始因為沒設置好過河之后對它們位置和是否在船上的變動,導致農夫獨自過河的時候,狼羊白菜和胡蘿卜都沒事,這就很明顯存在問題。最后說一下通過實驗的收獲,通過實驗更為熟練的掌握equals()的用法,類的繼承多態,這些老師上課講過,pta也練過,這次的實驗無非是把它們融合在一起運用罷了,但是也鍛煉鞏固了我們所學會的東西,同時這實驗的開放性也高有什么樣的想法都可以自己去嘗試,提高了我們對所學知識運用的熟練度。當然這次的代碼我感覺還有很大的改善空間,比如說進一步降低代碼的耦合性,進而讓減輕更改時的復雜性。
六、附錄
代碼:
package 農夫過河;
public class Cabbage extends object{
public void showStatus() {
System.out.println("cabbage is alive :"+isAlive+" cabbage has Cross :"+hasCross);
}
}
package 農夫過河;
public class Carrot extends object{
public void showStatus() {
System.out.println("carrot is alive :"+isAlive+" carrot has Cross :"+hasCross);
}
}
package 農夫過河;
public class Farmer extends object{
public void showStatus() {
System.out.println("Farmer has Cross :"+hasCross);
}
}
package 農夫過河;
import java.util.Scanner;
public class Game {
Wolf wolf;
Sheep sheep;
Cabbage cabbage;
Farmer farmer;
GameGui GameGui;
Rabbit rabbit;
Carrot carrot;
Game() {
wolf = new Wolf();
sheep = new Sheep();
cabbage = new Cabbage();
farmer = new Farmer();
rabbit = new Rabbit();
carrot = new Carrot();
GameGui=new GameGui();
}
protected void play(){
Scanner input = new Scanner(System.in);
int choice = 0,choice1 = 0; //用戶輸入選擇
boolean gameOver=false,//游戲結束標志,默認為false,代表游戲進行中,未結束
win=false; //游戲輸贏標志,默認為false,代表未贏得游戲。
System.out.println("請選擇模式1.舊規則 2.新規則");
choice = input.nextInt();
while(!gameOver)
{
GameGui.menu(choice);
choice1 = input.nextInt();
switch(choice1)
{
case 0:
break;
case 1:/* 農夫獨自過河的處理 */
farmer.setcrossRiver(!farmer.getcrossRiver());
break;
case 2:/* 農夫帶狼的處理 */
if(farmer.gethasCross()==wolf.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
wolf.setcrossRiver(!wolf.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
break;
case 3:/* 農夫帶羊的處理 */
if(farmer.gethasCross()==sheep.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
sheep.setcrossRiver(!sheep.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
break;
case 4:/* 農夫帶白菜的處理 */
if(farmer.gethasCross()==cabbage.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
cabbage.setcrossRiver(!cabbage.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
break;
case 5:/* 農夫帶兔子的處理 */
if(choice == 2) {
if(farmer.gethasCross()==rabbit.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
rabbit.setcrossRiver(!rabbit.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 6:/* 農夫帶胡蘿卜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==carrot.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
carrot.setcrossRiver(!carrot.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 7:/* 農夫帶狼和兔子的處理 */
if(choice == 2) {
if(farmer.gethasCross()==wolf.gethasCross()&&farmer.gethasCross()==rabbit.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
wolf.setcrossRiver(!wolf.getcrossRiver());
rabbit.setcrossRiver(!rabbit.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 8:/* 農夫帶狼和羊的處理 */
if(choice == 2) {
if(farmer.gethasCross()==wolf.gethasCross()&&farmer.gethasCross()==sheep.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
wolf.setcrossRiver(!wolf.getcrossRiver());
sheep.setcrossRiver(!sheep.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 9:/* 農夫帶狼和白菜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==wolf.gethasCross()&&farmer.gethasCross()==cabbage.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
wolf.setcrossRiver(!wolf.getcrossRiver());
cabbage.setcrossRiver(!cabbage.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 10:/* 農夫帶狼和胡蘿卜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==wolf.gethasCross()&&farmer.gethasCross()==carrot.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
wolf.setcrossRiver(!wolf.getcrossRiver());
carrot.setcrossRiver(!carrot.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 11:/* 農夫帶羊和兔子的處理 */
if(choice == 2) {
if(farmer.gethasCross()==sheep.gethasCross()&&farmer.gethasCross()==rabbit.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
sheep.setcrossRiver(!sheep.getcrossRiver());
rabbit.setcrossRiver(!rabbit.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 12:/* 農夫帶羊和白菜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==sheep.gethasCross()&&farmer.gethasCross()==cabbage.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
sheep.setcrossRiver(!sheep.getcrossRiver());
cabbage.setcrossRiver(!cabbage.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 13:/* 農夫帶羊和胡蘿卜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==sheep.gethasCross()&&farmer.gethasCross()==carrot.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
sheep.setcrossRiver(!sheep.getcrossRiver());
carrot.setcrossRiver(!carrot.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 14:/* 農夫帶兔子和白菜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==rabbit.gethasCross()&&farmer.gethasCross()==cabbage.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
rabbit.setcrossRiver(!rabbit.getcrossRiver());
cabbage.setcrossRiver(!cabbage.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 15:/* 農夫帶兔子和胡蘿卜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==rabbit.gethasCross()&&farmer.gethasCross()==carrot.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
rabbit.setcrossRiver(!rabbit.getcrossRiver());
carrot.setcrossRiver(!carrot.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
case 16:/* 農夫帶胡蘿卜和白菜的處理 */
if(choice == 2) {
if(farmer.gethasCross()==carrot.gethasCross()&&farmer.gethasCross()==cabbage.gethasCross()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
carrot.setcrossRiver(!carrot.getcrossRiver());
cabbage.setcrossRiver(!cabbage.getcrossRiver());
}
else
System.out.println("操作錯誤,請選擇有效操作!");
}
else
System.out.println("請輸入范圍內的值");
break;
default: System.out.println("請輸入范圍內的值");
}
if(farmer.getcrossRiver()) {
farmer.setcrossRiver(!farmer.getcrossRiver());
farmer.sethasCross(!farmer.gethasCross());}
if(sheep.getcrossRiver())
{
sheep.setcrossRiver(!sheep.getcrossRiver());
sheep.sethasCross(!sheep.gethasCross());
}
if(wolf.getcrossRiver())
{
wolf.setcrossRiver(!wolf.getcrossRiver());
wolf.sethasCross(!wolf.gethasCross());
}
if(cabbage.getcrossRiver())
{
cabbage.setcrossRiver(!cabbage.getcrossRiver());
cabbage.sethasCross(!cabbage.gethasCross());
}
if(choice==2)
{
if(carrot.getcrossRiver())
{
carrot.setcrossRiver(!carrot.getcrossRiver());
carrot.sethasCross(!carrot.gethasCross());
}
if(rabbit.getcrossRiver())
{
rabbit.setcrossRiver(!rabbit.getcrossRiver());
rabbit.sethasCross(!rabbit.gethasCross());
}
rabbit.eatCabbageandCarrot(cabbage,farmer,carrot,choice);//兔子吃白菜和胡蘿卜
}
wolf.eatSheepandRabbit(sheep,farmer,rabbit,choice);//狼吃羊和兔子,如果羊不在同一邊,則吃不到,如果在同一邊,羊被吃
sheep.eatCabbageandCarrot(cabbage,farmer,carrot,choice);//同上
GameGui.showStatus(farmer,wolf,sheep,cabbage,rabbit,carrot,choice);
if(choice1==0)
gameOver=true;
else
gameOver = isGameOver(choice);
}
win=this.hasWin(choice);
if(win) {
System.out.println("game over: you win !");
}else {
System.out.println("game over: you lose !");
}
input.close();
}
/*
* 判斷游戲是否結束
* 輸入:無
* 運算:羊、白菜任一實體被吃,游戲結束,或者狼、羊、白菜均未被吃且全部渡過河,游戲結束
* 輸出:游戲結束--返回true ,未結束--返回false
*/
public boolean isGameOver(int choice) {
if(sheep.getisAlive()==false||cabbage.getisAlive()==false||rabbit.getisAlive()==false||carrot.getisAlive()==false) {
return true;
}
if(wolf.gethasCross()&&sheep.gethasCross()&&cabbage.gethasCross()) {
return true;
}
if(choice==2&&rabbit.gethasCross()&&carrot.gethasCross()) {
return true;
}
return false;
}
/*
* 判斷游戲是否勝利
* 前置條件:游戲結束
* 輸入:無
* 運算:狼、羊、白菜均未被吃且全部渡過河,游戲勝利,否則失敗
* 輸出:游戲勝利--返回true ,失敗--返回false
*/
public boolean hasWin(int choice) {
if(sheep.getisAlive()==false||cabbage.getisAlive()==false||rabbit.getisAlive()==false||carrot.getisAlive()==false) {
return false;
}
if(wolf.gethasCross()&&sheep.gethasCross()&&cabbage.gethasCross()) {
return true;
}else
if(choice==2&&rabbit.gethasCross()&&carrot.gethasCross()){
return true;
}else
return false;
}
}
package 農夫過河;
public class GameGui {
public void menu(int choice)
{
/* 顯示菜單 */
System.out.println("==================Please choose operation============");
System.out.println("\t==========1:Cross the river alone===========");
System.out.println("\t==========2:Cross the river with wolf=========");
System.out.println("\t==========3:Cross the river with sheep============");
System.out.println("\t==========4:Cross the river with cabbage==========");
if(choice==2) {
System.out.println("\t==========5:Cross the river with rabbit============");
System.out.println("\t==========6:Cross the river with carrot==========");
System.out.println("\t==========7:Cross the river with wolf and rabbit===========");
System.out.println("\t==========8:Cross the river with wolf and sheep=========");
System.out.println("\t==========9:Cross the river with wolf and cabbage============");
System.out.println("\t==========10:Cross the river with wolf and carrot==========");
System.out.println("\t==========11:Cross the river with sheep and rabbit===========");
System.out.println("\t==========12:Cross the river with sheep and cabbage=========");
System.out.println("\t==========13:Cross the river with sheep and carrot============");
System.out.println("\t==========14:Cross the river with rabbit and cabbage==========");
System.out.println("\t==========15:Cross the river with rabbit and carrot============");
System.out.println("\t==========16:Cross the river with carrot and cabbage==========");
}
System.out.println("\t==========0:Quit===============");
System.out.println("===================================================");
System.out.println("Input the number:");
}
public void showStatus(Farmer farmer, Wolf wolf, Sheep sheep, Cabbage cabbage,Rabbit rabbit,Carrot carrot,int choice) {
/* 輸出農夫、各種動物、物品的狀態(生存、位置) */
farmer.showStatus();
wolf.showStatus();
sheep.showStatus();
cabbage.showStatus();
if(choice==2) {
rabbit.showStatus();
carrot.showStatus();
}
}
}
package 農夫過河;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Game game = new Game();
game.play();
}
}
package 農夫過河;
public class object {
boolean crossRiver=false;
boolean hasCross=false;
boolean isAlive=true;
public void showStatus() {
System.out.println();
}
public void eat() {
return ;
}
public void setcrossRiver(boolean a) {
crossRiver=a;
}
public void sethasCross(boolean a) {
hasCross=a;
}
public void setisAlive(boolean a) {
isAlive=a;
}
public boolean getcrossRiver() {
return crossRiver;
}
public boolean gethasCross() {
return hasCross;
}
public boolean getisAlive() {
return isAlive;
}
}
package 農夫過河;
public class Rabbit extends object {
public void showStatus() {
System.out.println("Rabbit is alive :"+isAlive+" Rabbit has Cross :"+hasCross);
}
public void eatCabbageandCarrot(Cabbage cabbage,Farmer farmer,Carrot carrot,int choice) {
if((cabbage.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross)&&cabbage.getisAlive()==true)
cabbage.setisAlive(!(cabbage.getisAlive()));
if((carrot.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross)&&carrot.getisAlive()==true&&choice==2)
carrot.setisAlive(!(carrot.getisAlive()));
}
}
package 農夫過河;
public class Sheep extends object{
public void showStatus() {
System.out.println("Sheep is alive :"+isAlive+" Sheep has Cross :"+hasCross);
}
public void eatCabbageandCarrot(Cabbage cabbage,Farmer farmer,Carrot carrot,int choice) {
if((cabbage.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross)&&cabbage.getisAlive()==true)
cabbage.setisAlive(!(cabbage.getisAlive()));
if((carrot.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross)&&carrot.getisAlive()==true&&choice==2)
carrot.setisAlive(!(carrot.getisAlive()));
}
}
package 農夫過河;
public class Wolf extends object{
public void showStatus() {
System.out.println("Wolf is alive :"+isAlive+" Wolf has Cross :"+hasCross);
}
public void eatSheepandRabbit(Sheep sheep,Farmer farmer,Rabbit rabbit,int choice) {
if((sheep.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross))
sheep.setisAlive(!sheep.getisAlive()) ;
if((rabbit.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross)&&choice==2)
rabbit.setisAlive(!rabbit.getisAlive()) ;
}
}