南昌航空大学实验报告
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表示过河过程正在进行,虽然复杂化了一点,但是我感觉表述会更清晰点。通过这次实验收获还是挺大的,帮助我对课程上学的知识进行了更深的理解,也增强了我的实际写代码能力。
六、附录