南昌航空大學實驗報告
2021 年 10 月 17 日
課程名稱:面向對象程序設計B 實驗名稱: 類與對象(一)
指導教師評定: 簽名:
一、實驗目的
1、 掌握類與對象的基本概念;
2、 掌握類的聲明、創建與使用方法;
3、 掌握類的構造方法的定義與使用方法
4、 掌握類的成員變量、成員方法的定義與使用方法;
5、 理解類變量、類方法與實例變量、實例方法的區別;
6、 理解Java語言中包的概念以及package、import語句的使用;
二、實驗要求
1、 根據實驗步驟中提出的要求,編寫相應的Java程序;
2、 編譯、運行自己所編寫的Java程序;
3、 根據編譯與運行過程中所獲得的錯誤信息修改程序直至獲得正確的結果;
4、 記錄實驗中遇到的各類問題並以及解決辦法。
三、實驗步驟
1、 農夫過河問題:一個農夫帶着一匹狼、一只羊、一顆白菜要過河,河上只有一條船能夠渡河,而且農夫每次最多只能帶一個動物或物品過河。當農夫不在的時候狼會吃羊,羊會吃白菜。
請以代碼為基礎,將程序代碼補充完整,實現農夫過河游戲功能:由用戶選擇角色過河,系統自動判斷游戲的勝負:當出現有生物被吃掉的時候,游戲失敗,所有角色都到了河的另一邊,游戲成功。
(1) 主類,用於運行程序;
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();
}
}
(2) 游戲界面類,用於顯示界面;
package 農夫過河;
public class GameGui {
public void menu()
{
/* 顯示菜單 */
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==========");
System.out.println("\t==========0:Quit===============");
System.out.println("===================================================");
System.out.println("Input the number(0~4):");
}
public void showStatus(Farmer farmer, Wolf wolf, Sheep sheep, Cabbage cabbage) {
/* 輸出農夫、各種動物、物品的狀態(生存、位置) */
farmer.showStatus();
wolf.showStatus();
sheep.showStatus();
cabbage.showStatus();
}
}
(3) 游戲類,用於執行游戲;
package 農夫過河;
import java.util.Scanner;
public class Game {
Wolf wolf;
Sheep sheep;
Cabbage cabbage;
Farmer farmer;
//GameGui gui;
Game() {
wolf = new Wolf();
sheep = new Sheep();
cabbage = new Cabbage();
farmer = new Farmer();
}
protected void play() {
Scanner input = new Scanner(System.in);
int choice = 0; //用戶輸入選擇
boolean gameOver=false,//游戲結束標志,默認為false,代表游戲進行中,未結束
win=false; //游戲輸贏標志,默認為false,代表未贏得游戲。
while(!gameOver)
{
GameGui.menu();
choice = input.nextInt();
switch(choice)
{
case 0: gameOver=true;
break;
case 1:/* 農夫獨自過河的處理 */
farmer.crossRiver=!( farmer.crossRiver);
break;
case 2:/* 農夫帶狼的處理 */
farmer.crossRiver=!( farmer.crossRiver);
wolf.crossRiver=!( wolf.crossRiver);
break;
case 3:/* 農夫帶羊的處理 */
farmer.crossRiver=!( farmer.crossRiver);
sheep.crossRiver=!( sheep.crossRiver);
break;
case 4:/* 農夫帶白菜的處理 */
farmer.crossRiver=!( farmer.crossRiver);
cabbage.crossRiver=!( cabbage.crossRiver);
break;
}
wolf.eatSheep(sheep);//狼吃羊,如果羊不在同一邊,則吃不到,如果在同一邊,羊被吃
sheep.eatCabbage(cabbage);//同上
GameGui.showStatus(farmer,wolf,sheep,cabbage);
gameOver = isGameOver();
}
win=this.hasWin();
if(win) {
System.out.println("game over: you win !");
}else {
System.out.println("game over: you lose !");
}
input.close();
}
/*
* 判斷游戲是否結束
* 輸入:無
* 運算:羊、白菜任一實體被吃,游戲結束,或者狼、羊、白菜均未被吃且全部渡過河,游戲結束
* 輸出:游戲結束--返回true ,未結束--返回false
*/
public boolean isGameOver() {
if(sheep.isAlive==false||cabbage.isAlive==false) {
return true;
}
if(wolf.hasCross&&sheep.hasCross&&cabbage.hasCross) {
return true;
}
return false;
}
/*
* 判斷游戲是否勝利
* 前置條件:游戲結束
* 輸入:無
* 運算:狼、羊、白菜均未被吃且全部渡過河,游戲勝利,否則失敗
* 輸出:游戲勝利--返回true ,失敗--返回false
*/
public boolean hasWin() {
if(sheep.isAlive==false||cabbage.isAlive==false) {
return false;
}
if(wolf.hasCross&&sheep.hasCross&&cabbage.hasCross) {
return true;
}else {
return false;
}
}
}
(4) 游戲輸出示例:
==================Please choose operation============
==========1:Cross the river alone===========
==========2:Cross the river with wolf=========
==========3:Cross the river with sheep============
==========4:Cross the river with cabbage==========
==========0:Quit===============
===================================================
Input the number(0~4):
2
Farmer has Cross :true
Wolf is alive :true Wolf has Cross :true
Sheep is alive :true Sheep has Cross :false
Cabbage is alive:false Cabbage has Cross:false
game over: you lose !
具體補全代碼在源碼中。
2、 畫出整個設計代碼的所有類的類圖(含屬性、方法)。
- 請考慮整個代碼結構以及功能實現,簡述你對整個代碼結構的分析和理解,代碼是否存在問題,該如何改進。
我覺得整體的代碼框架是沒有問題的,整個代碼應該分為七個類,其中四個類分別用來記錄農夫,羊,狼,菜過河情況以及存活狀態,同時還要對它們進行封裝,將類里的屬性私有化,剩下的類分別寫游戲界面,游戲具體運行情況以及主類。代碼存在的主要問題就是缺少Wolf,Farmer,Cabbage和Sheep這四個類。
4.帶下划線的語句為什么會報錯,你是如何修改的。
代碼報錯:GameGui.menu();和GameGui.showStatus(farmer,wolf,sheep,cabbage);
GameGui類沒調用構造,改進如下:
GameGui GameGui=new Game Gui();如下圖所示:
5.附上你的源代碼。
源碼如下:
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 農夫過河;
import java.util.Scanner;
public class Game {
Wolf wolf;
Sheep sheep;
Cabbage cabbage;
Farmer farmer;
GameGui GameGui;
Game() {
wolf = new Wolf();
sheep = new Sheep();
cabbage = new Cabbage();
farmer = new Farmer();
GameGui=new GameGui();
}
protected void play(){
Scanner input = new Scanner(System.in);
int choice = 0; //用戶輸入選擇
boolean gameOver=false,//游戲結束標志,默認為false,代表游戲進行中,未結束
win=false; //游戲輸贏標志,默認為false,代表未贏得游戲。
while(!gameOver)
{
GameGui.menu();
choice = input.nextInt();
switch(choice)
{
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;
}
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());
}
wolf.eatSheep(sheep,farmer);//狼吃羊,如果羊不在同一邊,則吃不到,如果在同一邊,羊被吃
sheep.eatCabbage(cabbage,farmer);//同上
GameGui.showStatus(farmer,wolf,sheep,cabbage);
if(choice==0)
gameOver=true;
else
gameOver = isGameOver();
}
win=this.hasWin();
if(win) {
System.out.println("game over: you win !");
}else {
System.out.println("game over: you lose !");
}
input.close();
}
/*
* 判斷游戲是否結束
* 輸入:無
* 運算:羊、白菜任一實體被吃,游戲結束,或者狼、羊、白菜均未被吃且全部渡過河,游戲結束
* 輸出:游戲結束--返回true ,未結束--返回false
*/
public boolean isGameOver() {
if(sheep.getisAlive()==false||cabbage.getisAlive()==false) {
return true;
}
if(wolf.gethasCross()&&sheep.gethasCross()&&cabbage.gethasCross()) {
return true;
}
return false;
}
/*
* 判斷游戲是否勝利
* 前置條件:游戲結束
* 輸入:無
* 運算:狼、羊、白菜均未被吃且全部渡過河,游戲勝利,否則失敗
* 輸出:游戲勝利--返回true ,失敗--返回false
*/
public boolean hasWin() {
if(sheep.getisAlive()==false||cabbage.getisAlive()==false) {
return false;
}
if(wolf.gethasCross()&&sheep.gethasCross()&&cabbage.gethasCross()) {
return true;
}else {
return false;
}
}
}
package 農夫過河;
public class GameGui {
public void menu()
{
/* 顯示菜單 */
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==========");
System.out.println("\t==========0:Quit===============");
System.out.println("===================================================");
System.out.println("Input the number(0~4):");
}
public void showStatus(Farmer farmer, Wolf wolf, Sheep sheep, Cabbage cabbage) {
/* 輸出農夫、各種動物、物品的狀態(生存、位置) */
farmer.showStatus();
wolf.showStatus();
sheep.showStatus();
cabbage.showStatus();
}
}
package 農夫過河;
public class Cabbage {
private boolean crossRiver=false;
private boolean hasCross=false;
private boolean isAlive=true;
public void showStatus() {
System.out.println("cabbage is alive :"+isAlive+" cabbage has Cross :"+hasCross);
}
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 Farmer {
private boolean crossRiver=false;
private boolean hasCross=false;
public void showStatus() {
System.out.println("Farmer has Cross :"+hasCross);
}
public void setcrossRiver(boolean a) {
crossRiver=a;
}
public void sethasCross(boolean a) {
hasCross=a;
}
public boolean getcrossRiver() {
return crossRiver;
}
public boolean gethasCross() {
return hasCross;
}
}
package 農夫過河;
public class Sheep {
private boolean crossRiver=false;
private boolean hasCross=false;
private boolean isAlive=true;
public void showStatus() {
System.out.println("Sheep is alive :"+isAlive+" Sheep has Cross :"+hasCross);
}
public void eatCabbage(Cabbage cabbage,Farmer farmer) {
if((cabbage.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross))
cabbage.setisAlive(!(cabbage.getisAlive()));
}
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 Wolf {
private boolean crossRiver=false;
private boolean hasCross=false;
private boolean isAlive=true;
public void showStatus() {
System.out.println("Wolf is alive :"+isAlive+" Wolf has Cross :"+hasCross);
}
public void eatSheep(Sheep sheep,Farmer farmer) {
if((sheep.gethasCross()==this.hasCross)&&(farmer.gethasCross()!=this.hasCross))
sheep.setisAlive(!sheep.getisAlive()) ;
}
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;
}
}
四、實驗結果
游戲通關流程如下:
若游戲失敗或直接退出如下:
五、實驗小結
這次實驗是分兩次進行的,第一次是補全代碼正常運行就行,第二次則是在原基礎上進行封裝處理,整個實驗都是對所學的知識進行校驗,難度不是很大,但需要處理的細節還是比較多的,比如說hascross與crossriver,最開始我是將hascross去掉,全部用crossriver來表示,一樣能實現,后來我又改成hascross表示狀態,crossriver表示過河過程正在進行,雖然復雜化了一點,但是我感覺表述會更清晰點。通過這次實驗收獲還是挺大的,幫助我對課程上學的知識進行了更深的理解,也增強了我的實際寫代碼能力。
六、附錄