面向对象程序设计 - 农夫过河 - Java

农夫过河 - Java

概述

胜利条件

  • 所有单位安全渡河

游戏模式

  • 经典模式(农夫,狼,羊,菜),狼会吃羊、羊会吃菜,小船最大承载量为 2
  • 全新模式(农夫,狼,羊,菜,兔子,胡萝卜),狼会吃羊、羊会吃菜、兔子会吃胡萝卜,小船最大承载量为 3
  • 地狱模式(农夫,狼,羊,菜,兔子,胡萝卜),狼会吃羊、狼会吃兔子、羊会吃菜、兔子会吃白菜、兔子会吃胡萝卜,小船最大承载量为 3

用到的知识

  • 继承,封装,多态

待完善

  • 逻辑不通的地方(在农夫不在某对象旁边时,仍然可带其过河)
  • 优化创建实体时的个性的播报(多了两个只用来个性播报的空壳类Wolf,Sheep)(解决方法:在构造函数加一个创建时要说的话)
  • 输出失败原因
  • 增加船的使用次数和状态显示
  • 直接给isAlivecrossRiver赋初值而不必使用构造器
  • 优化携带对象过河的交互,允许乱序输入过河对象
  • 更多游戏角色
  • 地狱模式
  • 优化ArrayList crosses
  • 优化职责
  • 在菜单输出之后输出 ”不在同一侧“ 的提醒
  • 优化菜单(只显示农夫侧的对象(states也不必show了))(逆向优化?)
  • 添加挑战模式(用最少的操作次数完成渡河才可以赢)
  • 优化GameGui
  • 使用抽象/接口

码源

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        GameGui.welcome();
        switch (in.nextInt()) {
            case 1: {
                Game game = new Game();
                game.play();
                break;
            }
            case 2: {
                Game2 game2 = new Game2();
                game2.play();
                break;
            }
            case 3: {
                Game3 game3 = new Game3();
                game3.play();
                break;
            }
        }
    }
}

class Game {

    Objs wolf, sheep, cabbage, farmer;
    Transporter boat;

    Objs[] crosser;

    Game() {
        boat = new Transporter("我是送大家去对岸的", "Boat", 2, 11);
        wolf = new Objs("啊呜~~~我", "Wolf", "狼又回来了");
        sheep = new Objs("咩咩,我是可爱的小羊", "Sheep");
        cabbage = new Objs("NONE", "Cabbage");
        farmer = new Objs("NONE", "Farmer");
    }

    protected void play() {
        crosser = getCrosses();
        while (true) {
            GameGui.menu(crosser);

            boolean[] choices = getChoices();

            if (cantCross(choices)) continue;

            boat.crossRiver(choices, crosser);

            AnimalsToEat();

            showStatus();
            if (isGameOver()) break;
        }
        over(crosser);
    }

    public Objs[] getCrosses() {
        return new Objs[]{null, farmer, wolf, sheep, cabbage};
    }

    private boolean[] getChoices() {
        Scanner input = new Scanner(System.in);
        boolean[] choices = new boolean[10];
        boolean Wrong;
        do {
            Wrong = false;
            try {
                while (input.hasNext()) {
                    String s = input.next();
                    if (s.equals("0")) System.exit(0);
                    if (s.equals("#")) break;
                    int id = Integer.parseInt(s);
                    choices[id] = true;
                }
            } catch (Exception e) {
                System.out.println("输入有误,请重新输入!");
                Wrong = true;
            }
        } while (Wrong);
        return choices;
    }

    // 判断是否有农夫,判断是否超载
    public boolean cantCross(boolean[] choices) {
        if (!choices[1] || outOfObjs(choices)) {
            System.out.println("!!!您的输入不可实现!!!");
            return true;
        }
        if (boat.overMaxLoad(choices)) {
            System.out.println("超载啦!走不成哦!");
            return true;
        }
        return false;
    }

    // 判断是否有超出对象编号的选项
    private boolean outOfObjs(boolean[] choices) {
        for (int i = crosser.length; i < choices.length; i++) {
            if (choices[i]) return true;
        }
        return false;
    }

    // 让动物们可以去吃
    public void AnimalsToEat() {
        wolf.eat(farmer, sheep);//狼吃羊,如果羊不在同一边,则吃不到,如果在同一边,羊被吃
        sheep.eat(farmer, cabbage);//同上
    }

    /*
     * 判断游戏是否结束
     * 运算:羊、白菜任一个实体被吃,游戏结束,或者狼、羊、白菜均未被吃且全部渡过河,游戏结束
     * 输出:游戏结束--返回true ,未结束--返回false
     */
    public boolean isGameOver() {
        for (Objs o : crosser) if (o != null && o.isDead()) return true;
        for (Objs o : crosser) if (o != null && !o.getHasCross()) return false;
        return true;
    }

    /*
     * 判断游戏是否胜利
     * 前置条件:游戏结束
     * 运算:狼、羊、白菜均未被吃且全部渡过河,游戏胜利,否则失败
     * 输出:游戏胜利--返回true ,失败--返回false
     */
    public boolean hasWin(Objs[] objs) {
        for (Objs o : objs) if (o != null && o.isDead()) return false;
        for (Objs o : objs) if (o != null && !o.getHasCross()) return false;
        return true;
    }


    // 显示状态
    private void showStatus() {
        /* 输出农夫、各种动物、物品的状态(生存、位置) */
        System.out.println("====================== States =======================");
        for (Objs t : crosser) if (t != null) t.showStatus();
        boat.showStatus();
    }


    // 结束游戏
    protected void over(Objs[] objs) {
        if (hasWin(objs)) {
            System.out.println("\n*****************************************************");
            System.out.println("*************** game over: you win ! ****************");
        } else {
            System.out.println();
            howLose(boat, objs);
            System.out.println("*****************************************************");
            System.out.println("*************** game over: you lose ! ***************");
        }
        System.out.println("*****************************************************");
        System.exit(0);
    }

    // 输出失败原因
    protected void howLose(Transporter boat, Objs[] objs) {
        if (boat.isDead()) System.out.println("");
        for (Objs obj : objs)
            if (obj != null && obj.isDead()) System.out.println("");
    }
}

class Game2 extends Game {

    Objs rabbit, carrot;

    public Game2() {
        rabbit = new Objs("我是最机灵的兔子", "Rabbit");
        carrot = new Objs("NONE", "Carrot");
        boat.setTakingNum(3);
        boat.setUseTime(13);
    }

    @Override
    public Objs[] getCrosses() {
        return new Objs[]{null, farmer, wolf, sheep, rabbit, cabbage, carrot};
    }

    @Override
    public void AnimalsToEat() {
        wolf.eat(farmer, sheep);    //若wolf与sheep在同一侧且农夫不在,wolf会吃掉sheep
        wolf.eat(farmer, rabbit);
        sheep.eat(farmer, cabbage);
        rabbit.eat(farmer, carrot);
    }

}

class Game3 extends Game2 {

    @Override
    public void AnimalsToEat() {
        wolf.eat(farmer, sheep);    //若wolf与sheep在同一侧且农夫不在,wolf会吃掉sheep
        wolf.eat(farmer, rabbit);
        sheep.eat(farmer, cabbage);
        sheep.eat(farmer, carrot);
        rabbit.eat(farmer, carrot);
        rabbit.eat(farmer, cabbage);
    }
}

class GameGui {

    public static void welcome() {
        System.out.println("选择要进行的游戏模式:\n" +
                "1:经典模式(农夫,狼,羊,菜):(农夫不在身边时)狼吃羊、羊吃菜\n" +
                "2:全新模式(农夫,狼,羊,菜,兔子,萝卜):(农夫不在身边时)狼吃羊、狼吃兔、羊吃菜、兔子吃萝卜\n" +
                "3:地狱模式(农夫,狼,羊,菜,兔子,萝卜):(农夫不在身边时)狼吃羊、狼吃兔、羊吃菜、羊吃萝卜、兔子吃萝卜、兔子吃菜");
    }

    public static void menu(Objs[] crosser) {
        /* 显示菜单 */
        System.out.println("============== Please choose operation ==============");
        System.out.println("请将要渡河的对象的序号以空格间隔输入,并以 # 结尾来确认您的输入");
        System.out.println("0:退出游戏");
        for (int i = 1; i < crosser.length - 1; i += 2) {
            System.out.println(i + ":" + crosser[i].getName() + " \t" + (i + 1) + ":" + crosser[i + 1].getName());
        }
    }

}

class Objs {

    private final String name;
    private boolean isAlive = true;     //初始化 活
    private boolean hasCross = false;

    public Objs(String Saying, String name) {
        this.name = name;
        if (!Saying.equals("NONE")) System.out.println(Saying + " " + " " + name);
    }

    // 为狼重载出场播报
    public Objs(String Saying1, String name, String Saying2) {
        this.name = name;
        if (!Saying1.equals("NONE")) System.out.println(Saying1 + " " + name + " " + Saying2);
    }

    /* 输出农夫、各种动物、物品的状态(生存、位置) */
    public void showStatus() {
        System.out.printf("\t\t%-8s \t%11s CrossedRiver\n", name, hasCross ? "is" : "isNot");
    }

    public void eat(Objs farmer, Objs objs2) {
        if (hasCross == objs2.getHasCross()) {//调用者和传入者在一起
            if (hasCross != farmer.getHasCross()) {//是否和农夫在一起
                killObj(objs2);
            }
        }
    }

    private static void killObj(Objs objs) {
        objs.isAlive = false;
    }

    /* Getter And Setter*/
    public String getName() {
        return name;
    }

    public boolean isDead() {
        return !isAlive;
    }

    public boolean getHasCross() {
        return hasCross;
    }

    public void cross() {
        this.hasCross = !this.hasCross;
    }
}

class Transporter extends Objs {

    private int takingNum;  //核载
    private int useTime;    //使用次数

    public Transporter(String saying, String name, int takingNum, int useTime) {
        super(saying, name);
        this.takingNum = takingNum;
        this.useTime = useTime;
    }

    /*
     * 将所有对象运输到对岸
     * 使用次数减1
     */
    public void crossRiver(boolean[] choices, Objs[] objs) {
        for (int i = 2; i < objs.length; i++) {
            if (!choices[i]) continue;
            if (!onSameSide(objs[1], objs[i])) return;  //若某对象不在农夫旁边,则渡河失败
        }
        for (int i = 0; i < choices.length; i++) if (choices[i]) objs[i].cross(); //使选择的对象过河
        useTime--;
    }

    // 是否超载
    protected boolean overMaxLoad(boolean[] choices) {
        int cnt = 0;
        for (boolean b : choices) if (b) cnt++;
        return cnt > takingNum;
    }

    @Override
    public void showStatus() {

        if (useTime > 7) System.out.println("\t\t" + getName() + " will be destroyed after " + useTime + " uses");
        else
            System.out.println("!!!!!!!! " + getName() + " will be destroyed after " + useTime + " uses" + " !!!!!!!!");
    }

    private static boolean onSameSide(Objs objs1, Objs objs2) {
        if (objs1.getHasCross() == objs2.getHasCross()) return true;
        else {
            System.out.println("!!!!" + objs1.getName() + " and " + objs2.getName() + " are not on the same side!!!!");
            return false;
        }
    }

    /* Getter And Setter */
    @Override
    public boolean isDead() {
        return useTime <= 0;
    }

    public void setTakingNum(int takingNum) {
        this.takingNum = takingNum;
    }

    public void setUseTime(int useTime) {
        this.useTime = useTime;
    }

}

精美截图

不会有人赢不了吧

面向对象程序设计 - 农夫过河 - Java_第1张图片

若本贴对您有帮助,欢迎点赞收藏!

由于作者时间、能力有限,代码中难免有不足之处,还望读者海涵并不吝赐教。

你可能感兴趣的:(#,Java,java,intellij-idea)