首页 > 解决方案 > 重现 Bagh Chan 游戏(老虎和山羊)

问题描述

基本上,对于家庭作业,我被要求重新创建一个名为 Bagn Chan 的小型印度游戏,我不知道从哪里开始。我已经得到了一些骨架代码,所有这些都附在后面。

** 不要求完整的解决方案,只是指导,尽管如果有人想做完整的解决方案,我会非常高兴 **

使用的 IDE 是 BlueJ,但是我只是不知道该怎么做,所以任何帮助都将不胜感激。

这是 GameViewer 类

public class GameViewer implements MouseListener
{
    // instance variables
    private int bkSize; // block size - all other measurements to be derived from bkSize
    private int brdSize; // board size
    private SimpleCanvas sc; // an object of SimpleCanvas to draw 
    private GameRules rules; // an object of GameRules
    private Board bd; // an object of Board
    private AIplayer ai; //an object of AIplayer
    
    // 2D coordinates of valid locations on the board in steps of block size    
    public static final int[][] locs = {{1,1},{1,4},{1,7},{4,7},{7,7},{7,4},{7,1},{4,1},
                                 {2,2},{2,4},{2,6},{4,6},{6,6},{6,4},{6,2},{4,2},
                                 {3,3},{3,4},{3,5},{4,5},{5,5},{5,4},{5,3},{4,3}};
    // source and destination for the goat moves                             
    private int[] mov = {-1,-1}; //-1 means no selection

    /**
     * Constructor for objects of class GameViewer
     * Initializes instance variables and adds mouse listener.
     * Draws the board.
     */
    public GameViewer(int bkSize)
    {        
        this.bkSize = bkSize;
        brdSize = bkSize*8;
        sc = new SimpleCanvas("Tigers and Goats", brdSize, brdSize, Colour.BLUE);
        sc.addMouseListener(this);           
        rules = new GameRules();
        bd = new Board();
        ai = new AIplayer();              
        drawBoard();                      
    }
    
    /**
     * Constructor with default block size
     */
    public GameViewer( )
    {
        this(80);
    }
    
    /**
     * Draws the boad lines and the pieces as per their locations.
     * Drawing of lines is provided, students to implement drawing 
     * of pieces and number of goats.
     */
    private void drawBoard()
    {
        sc.drawRectangle(0,0,brdSize,brdSize,Color.BLUE); //wipe the canvas
        
        //draw shadows of Goats and Tigers - not compulsory //////////////////////        
        
        // Draw the lines
        for(int i=1; i<9; i++)
        {
            //diagonal and middle line
            sc.drawLine(locs[i-1][0]*bkSize, locs[i-1][1]*bkSize,
                        locs[i+15][0]*bkSize, locs[i+15][1]*bkSize, Color.red);
           
            if(i==4 || i==8) continue; //no more to draw at i=4,8
            // vertical line
            sc.drawLine(i*bkSize, i*bkSize,
                        i*bkSize, brdSize-i*bkSize,Color.white);            
            // horizontal line
            sc.drawLine(i*bkSize,         i*bkSize,
                        brdSize-i*bkSize, i*bkSize, Color.white);  
            
        }
        
        // TODO 10 
        // Draw the goats and tigers. (Drawing the shadows is not compulsory)
        // Display the number of goats        
        
    }
    
    /**
     * If vacant, place a goat at the user clicked location on board.
     * Update goat count in rules and draw the updated board
     */
    public void placeGoat(int loc) 
    {   
        //TODO 2
                               
    }
    
    /**
     * Calls the placeTiger method of AIplayer to place a tiger on the board.
     * Increments tiger count in rules.
     * Draws the updated board.
     */
    public void placeTiger() 
    {   
        //TODO 13
                
    }
    
    /**
     * Toggles goat selection - changes the colour of selected goat.
     * Resets selection and changes the colour back when the same goat is clicked again.
     * Selects destination (if vacant) to move and calls moveGoat to make the move.
     */
    public void selectGoatMove(int loc) 
    {   
        //TODO 16
        
    }
    
    /**
     * Make the user selected goat move only if legal otherwise set the destination to -1 (invalid).
     * If did make a goat move, then update board, draw the updated board, reset mov to -1,-1.
     * and call tigersMove() since after every goat move, there is a tiger move.
     */
    public void moveGoat() 
    {   
        //TODO 18        
        
    }
 
    /**
     * Call AIplayer to make its move. Update and draw the board after the move.
     * If Tigers cannot move, display "Goats Win!".
     * If goats are less than 6, display "Tigers Win!".
     * No need to terminate the game.
     */
    public void tigersMove()
    {
        //TODO 20
                               
    }
        
    /**
     * Respond to a mouse click on the board. 
     * Get a valid location nearest to the click (from GameRules). 
     * If nearest location is still far, do nothing. 
     * Otherwise, call placeGoat to place a goat at the location.
     * Call this.placeTiger when it is the tigers turn to place.
     * When the game changes to move stage, call selectGoatMove to move 
     * the user selected goat to the user selected destination.
     */
    public void mousePressed(MouseEvent e) 
    {
        SimpleCanvas sc = new SimpleCanvas();
        sc.addMouseListener(e);
    }
    
    
    public void mouseClicked(MouseEvent e) {int x=e.getX();int y=e.getY();}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

这是类 GameRules

{
    // Instance variables to maintain whose move it is
    private boolean moveStage; 
    private boolean goatsTurn;
    private int numGoats; //the number of goats on the board
    private int numTigers; //the number of tigers on the board
    private final int MAXGOATS = 12;

    /**
     * Constructor for objects of class GameRules
     */
    public GameRules()
    {              
        moveStage = false;
        goatsTurn = true;
        numGoats = 0;
        numTigers = 0;
    }       
    
    /**
     * returns moveStage
     */
    public boolean isMoveStage()
    {
        return moveStage;
    }
    
    /**
     * returns true iff it is goats turn
     */
    public boolean isGoatsTurn()
    {
        return goatsTurn;
    }    
    
    
    /**
     * Adds (+1 or -1) to goat numbers.
     * Changes the goatsTurn and moveStage as per rules.
     */
    public void addGoat(int n)
    {
         //TODO 12
        numGoats = numGoats + n;
        if (numGoats == 12)
        {
            moveStage = true;
            goatsTurn = false;
        }
    }
    
    /**
     * returns number of goats
     */
    public int getNumGoats()
    {
        return numGoats;
    }
    
    /**
     * increments tigers and gives turn back to goats
     */
    public void incrTigers()
    {
        //TODO 16
        numTigers = numTigers + 1;
        goatsTurn = true;
        if (numTigers > 3){
            numTigers = 3;
            throw new IllegalArgumentException("Maximum of 3 Tigers allowed");
        }
        if (numTigers == 3){
            moveStage = true;
        }
    }
        
    /**
     * Returns the nearest valid location (0-23) on the board to the x,y mouse click.
     * Locations are described in project description on LMS.
     * You will need bkSize & GameViewer.locs to compute the distance to a location.
     * If the click is close enough to a valid location on the board, return 
     * that location, otherwise return -1 (when the click is not close to any location).
     * Choose a threshold for proximity of click based on bkSize.
     */    
    public int nearestLoc(int x, int y, int bkSize)
    {
        int loc = -1;
        
        int buffer = (2*bkSize/10);
        
        int oneHigh = (bkSize+buffer);
        int oneLow = (bkSize-buffer);
        int twoHigh = (2*bkSize+buffer);
        int twoLow = (2*bkSize-buffer);
        int threeHigh = (3*bkSize+buffer);
        int threeLow = (3*bkSize-buffer);
        int fourHigh = (4*bkSize+buffer);
        int fourLow = (4*bkSize-buffer);
        int fiveHigh = (5*bkSize+buffer);
        int fiveLow = (5*bkSize-buffer);
        int sixHigh = (6*bkSize+buffer);
        int sixLow = (6*bkSize-buffer);
        int sevenHigh = (7*bkSize+buffer);
        int sevenLow = (7*bkSize-buffer);
        
        if (oneHigh >= x && x >= oneLow) {
            if (oneHigh >= y && y >= oneLow){
                x = 1;
                y = 1;
                loc = 0;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 1;
                y = 4;
                loc = 1;
            }
            if (sevenHigh >= y && y >= sevenLow){
                x = 1;
                y = 7;
                loc = 2;
            }
        }
        if (twoHigh >= x && x >= twoLow) {
            if (twoHigh >= y && y >= twoLow){
                x = 2;
                y = 2;
                loc = 8;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 2;
                y = 4;
                loc = 9;
            }
            if (sixHigh >= y && y >= sixLow){
                x = 2;
                y = 6;
                loc = 10;
            }
        }
        if (threeHigh >= x && x >= threeLow) {
            if (threeHigh >= y && y >= threeLow){
                x = 3;
                y = 3;
                loc= 16;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 3;
                y = 4;
                loc = 17;
            }
            if (fiveHigh >= y && y >= fiveLow){
                x = 3;
                y = 5;
                loc = 18;
            }
        }
        
        if (sevenHigh >= x && x >= sevenLow) {
            if (oneHigh >= y && y >= oneLow){
                x = 7;
                y = 1;
                loc = 6;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 7;
                y = 4;
                loc = 5;
            }
            if (sevenHigh >= y && y >= sevenLow){
                x = 7;
                y = 7;
                loc = 4;
            }
        }
        if (sixHigh >= x && x >= sixLow) {
            if (twoHigh >= y && y >= twoLow){
                x = 6;
                y = 2;
                loc = 14;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 6;
                y = 4;
                loc = 13;
            }
            if (sixHigh >= y && y >= sixLow){
                x = 6;
                y = 6;
                loc = 12;
            }
        }
        if (fiveHigh >= x && x >= fiveLow) {
            if (threeHigh >= y && y >= threeLow){
                x = 5;
                y = 3;
                loc = 22;
            }
            if (fourHigh >= y && y >= fourLow){
                x = 5;
                y = 4;
                loc = 21;
            }
            if (fiveHigh >= y && y >= fiveLow){
                x = 5;
                y = 5;
                loc = 20;
            }
        }
        
        if (fourHigh >= x && x >= fourLow){
            if (twoHigh >= y && y >= twoLow){
                x = 4;
                y = 2;
                loc = 15;
            }
            if (fiveHigh >= y && y >= fiveLow){
                x = 4;
                y = 5;
                loc = 19;
            }
            if (sixHigh >= y && y >= sixLow){
                x = 4;
                y = 6;
                loc = 11;
            }
            if (sevenHigh >= y && y >= sevenLow){
                x = 4;
                y = 7;
                loc = 3;
            }
            if (oneHigh >= y && y >= oneLow){
                x = 4;
                y = 1;
                loc = 7;
            }
            if (threeHigh >= y && y >= threeLow){
                x = 4;
                y = 3;
                loc = 23;
            }
        }
      
        return loc;    
    }
    
    /**
     * Returns true iff a move from location a to b is legal, otherwise returns false.
     * For example: a,b = 1,2 -> true; 1,3 -> false; 7,0 -> true. Refer to the 
     * project description for details.
     * Throws an exception for illegal arguments.
     */
    public boolean isLegalMove(int a, int b)
    {
        //TODO 19 
        if (a == 7 & b == 8 | a == 8 & b == 7 | 
        a == 15 & b == 16 | a == 16 & b == 15 | 
        a<0 | b<0 | a>23 | b>23 ){
            throw new IllegalArgumentException("Move is illegal");
        }
        if (a == 0 & b == 7 | a == 7 & b == 0 | 
        a == 8 & b == 15 | a == 15 & b == 8 |
        a == 23 & b == 16 | a == 16 & b == 23){
            return true;
        }
        if (a - b == 8 | a - b == 1 | b - a == 8 | b - a == 1){
            return true;
        }
        else throw new IllegalArgumentException("Move is illegal");
    }
}

这是简单的画布

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

import java.util.List;
import java.util.*;

public class SimpleCanvas
{

    private JFrame     frame;
    private CanvasPane canvas;
    private Graphics2D graphic;
    private Image      canvasImage;
    private boolean    autoRepaint;
    
    /**
     * Creates and displays a SimpleCanvas of the specified size and background 
     */
    public SimpleCanvas(String title, int width, int height, Color bgColour) {
        frame = new JFrame();
        canvas = new CanvasPane();
        frame.setContentPane(canvas);
        frame.setTitle(title);
        canvas.setPreferredSize(new Dimension(width,height));
        frame.pack();
        Dimension size = canvas.getSize();
        canvasImage = canvas.createImage(size.width,size.height);
        graphic = (Graphics2D) canvasImage.getGraphics();
        graphic.setColor(bgColour);
        graphic.fillRect(0,0,size.width,size.height);
        graphic.setColor(Color.black);
        frame.setVisible(true);
        this.autoRepaint = true;
    }
    
    /**
     * Creates and displays a SimpleCanvas of size 400x400 with the
     * default title "SimpleCanvas" and with white background.
     */
    public SimpleCanvas() {
        this("SimpleCanvas", 400, 400, Color.white);
    }
    
    /** 
     * Draws a line on this SimpleCanvas from x1,y1 to x2,y2 with colour c.
     */
    public void drawLine(int x1, int y1, int x2, int y2, Color c) {
        setForegroundColour(c);
        graphic.drawLine(x1, y1, x2, y2);
        if (autoRepaint) canvas.repaint();
    }
    
    /** 
     * Draws a point on this SimpleCanvas at x,y with colour c.
     */
    public void drawPoint(int x, int y, Color c) {
        drawLine(x, y, x, y, c);
    }
    
    /** 
     * Draws a rectangle on this SimpleCanvas with sides parallel to the axes 
     * between x1,y1 and x2,y2 with colour c.
     */
    public void drawRectangle(int x1, int y1, int x2, int y2, Color c) {
        setForegroundColour(c);
        graphic.fillRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
        if (autoRepaint) canvas.repaint();
    }
    
    /** 
     * Draws a disc on this SimpleCanvas centred at x,y with radius r with colour c.
     */
    public void drawDisc(int x, int y, int r, Color c) {
        for (int i = x - r; i <= x + r; i++)
            for (int j = y - r; j <= y + r; j++)
                if (Math.pow(i-x, 2) + Math.pow(j-y, 2) <= Math.pow(r, 2)) 
                   drawPoint(i, j, c);
        if (autoRepaint) canvas.repaint();
    }
    
    /** 
     * Draws a circle on this SimpleCanvas centred at x,y with radius r with colour c.
     */
    public void drawCircle(int x, int y, int r, Color c) {
        for (int i = x - r; i <= x + r; i++)
            for (int j = y - r; j <= y + r; j++)
                if (Math.pow(i-x, 2) + Math.pow(j-y, 2) <= Math.pow(r,     2) &&
                    Math.pow(i-x, 2) + Math.pow(j-y, 2) >= Math.pow(r - 5, 2)) 
                   drawPoint(i, j, c);
        if (autoRepaint) canvas.repaint();
    }
    
    /**
     * Writes the String text on this SimpleCanvas at x,y with colour c.
     */
    public void drawString(String text, int x, int y, Color c) {
        setForegroundColour(c);
        graphic.drawString(text, x, y);
        if (autoRepaint) canvas.repaint();
    }
    
    /**
     * Writes the number n on this SimpleCanvas at x,y with colour c.
     */
    public void drawString(int n, int x, int y, Color c) {
        drawString(n + "", x, y, c);
    }
    
    /** 
     * Changes the colour for subsequent drawing on this SimpleCanvas.
     */
    public void setForegroundColour(Color newColour) {
        graphic.setColor(newColour);
    }
    
    /**
     * Gets the colour currently used for drawing on this SimpleCanvas.
     */
    public Color getForegroundColour() {
        return graphic.getColor();
    }
    
    /**
     * Changes the font for subsequent Strings on this SimpleCanvas.
     */
    
    public void setFont(Font newFont) {
        graphic.setFont(newFont);
    }
    
    /**
     * Gets the font currently used for Strings on this SimpleCanvas.
     */
    public Font getFont() {
        return graphic.getFont();
    }
    
    /**
     * Sets the repaint mode to either manual or automatic.
     */
    public void setAutoRepaint(boolean autoRepaint) {
        this.autoRepaint = autoRepaint;
    }
     
     
    /**
     * If this SimpleCanvas does not automatically repaint after each drawing command, 
     * this method can be used to cause a manual repaint.
     */
    public void repaint() {
        canvas.repaint();
    }
    
    /**
     * Causes execution to pause for the specified amount of time.
     * This is usually used to produce animations in an easy manner, 
     * by repeatedly drawing, pausing, and then redrawing an object.
     */
    public void wait(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ie) {
            System.out.println("Interruption in SimpleCanvas: " + ie);
        }
    }
    
    /**
     * Sets up this SimpleCanvas to respond to mouse input.
     */
    public void addMouseListener(MouseListener ml) {
        canvas.addMouseListener(ml);
    }
    
    /**
     * Sets up this SimpleCanvas to respond to mouse motion input.
     */
    public void addMouseMotionListener(MouseMotionListener mml) {
        canvas.addMouseMotionListener(mml);
    }
    
    class CanvasPane extends JPanel {
        public void paint(Graphics g) {
            g.drawImage(canvasImage,0,0,null);
        }
    }       
}

这是板已完成

public class Board
{
    // An enumated type for the three possibilities
    private enum Piece {GOAT, TIGER, VACANT};
    // 1-D Array representation of the board. Top left is 0, 
    // then goes anti-clockwise spiraling inward until 23
    Piece[] board;

    /**
     * Constructor for objects of class Board.
     * Initializes the board VACANT.
     */
    public Board()
    {
        board = new Piece[24];
        for (int i=0;i<24;i++)
            board[i] = Piece.VACANT;
       
    }

            
    /**
     * Checks if the location a is VACANT on the board
     */
    public boolean isVacant(int a)
    {
        //TODO 4
        return board[a] == Piece.VACANT;
    }
    
    /**
     * Sets the location a on the board to VACANT
     */
    public void setVacant(int a)
    {
        //TODO 5
        board[a] = Piece.VACANT;
    }
    
    /**
     * Checks if the location a on the board is a GOAT
     */
    public boolean isGoat(int a)
    {
        //TODO 6
        return board[a] == Piece.GOAT;
    }
    
    /**
     * Sets the location a on the board to GOAT
     */
    public void setGoat(int a)
    {
        //TODO 7
        board[a] = Piece.GOAT;
    }
    
    /**
     * Sets the location a on the board to TIGER
     */
    public void setTiger(int a)
    {
        //TODO 8
        board[a] = Piece.TIGER;
    }
    
    /**
     * Moves a piece by swaping the contents of a and b
     */
    public void swap(int a, int b)
    {
        //TODO 9
        Piece temp = board[a];
        board[a] = board[b];
        board[b] = temp;
    }
}

这是AIPlayer

import java.util.Random;
import java.util.*;
import java.io.*; 
import java.lang.*;

public class AIplayer
{
    private Random rn; // for random tiger or location selection
    private GameRules rul; // an instance of GameRules to check for legal moves
    private int[][] tigerLocs = {{-1},{-2},{-3}}; // location of tigers for convenience 
    private int ntigers; // number of tigers placed
    private Board bd;
    private GameViewer gv;
    // A 2D Array that maintains legal goat eating moves that tigers can perform, e.g. {0,8,16} means 
    // a tiger can jump from location 0 to 16 (or 16 to 0) to eat the goat at location 8 
    private final int[][] legalEats = {{0,1,2},{0,7,6},{0,8,16},{1,9,17},{2,10,18},{2,3,4},{3,11,19},
                                 {4,5,6},{4,12,20},{5,13,21},{6,14,22},{7,15,23},{8,9,10},{8,15,14},
                                 {10,11,12},{12,13,14},{16,17,18},{16,23,22},{18,19,20},{20,21,22}};  
    
    /**
     * Constructor for objects of class AIplayer.
     * Initializes instance variables.
     */
    public AIplayer()
    {
        // TODO 14
        ntigers = 0;
        
    }

    /**
     * Place tiger in a random VACANT location on the Board
     * Update the board, the tiger count and tigerLocs.
     */
    public void placeTiger(Board bd)
    {
        // TODO 15
        Random rn = new Random();
        int loc = rn.nextInt(23);
        
        if (bd.isVacant(loc) == false){
            placeTiger(bd);
        }
        
        if (bd.isVacant(loc) == true){
            bd.setTiger(loc);
            tigerLocs[ntigers][0] = loc;
            ntigers = ntigers + 1;
            System.out.println("A Tiger has appeared at location "+loc);
        }
        
        
    }
    
    /**
     * If possible to eat a goat, must eat and return 1
     * If cannot eat any goat, make a move and return 0
     * If cannot make any move (all Tigers blocked), return -1
     */
    public int makeAmove(Board bd)
    {
        if (eatGoat(bd))  return 1; // did eat a goat
        else if (simpleMove(bd)) return 0; // made a simple move
        else return -1; // could not move
    }
    
    /**
     * Randomly choose a tiger, move it to a legal destination and return true
     * if none of the tigers can move, return false.
     * Update the board and the tiger location (tigerLocs)
     */
    public boolean simpleMove(Board bd)
    {
        //TODO 21
        boolean result = false;
        
        Random rn = new Random();
        int tig = rn.nextInt(2);
        int loc = tigerLocs[tig][0];
        
        
        
        for (int z=23;z>=0; z--)
        {
            if (bd.isVacant(z)==true){
                System.out.println(loc+","+z);
                boolean isLegal = rul.isLegalMove(loc,z);
                if (isLegal == true)
                {
                    bd.swap(loc,z);
                    gv.drawBoard(0);
                    result = true;
                    return true;
                }
            }
        }
        
        
        return false; 
    }
    
    /**
     * If possible, eat a goat and return true otherwise return false.
     * Update the board and the tiger location (tigerLocs)
     */
    public boolean eatGoat(Board bd)
    {
        boolean eat = false;
        System.out.println(gv.locs[tigerLocs[1][0]][0]+","+gv.locs[tigerLocs[1][0]][1]);
        //for (int i = 0; i>=2; i++)
        //{
           // int loc = tigerLocs[i];
          //  for (int b = 0; b>=23; b++)
           // {
            //    if (loc == legalEats[b][0])
            //    {
            //        for (int c = 0; c >=23; c++)
            //        {
            //            if ((bd.isVacant(c) == true) && (legalEats[b][2] == c))
           //             {
           //                 int goat = legalEats[b][1];
          ///                  if (bd.isGoat(goat))
          //                  {
          //                      bd.setVacant(b);
          //                      bd.setTiger(c);
          //                      gv.drawBoard(0);
          //                      eat = true;
          //                  }
         //               }
         //           }
         //       }
        //    }
        //}
        for (int i=0; i>=2; i++)
        {
            int loc = tigerLocs[i][0];
            System.out.println(loc);
            
            for (int j=0; j>=19; j++)
            {
                if ((loc==legalEats[j][0]) || (loc==legalEats[j][2]))
                {
                    if (bd.isGoat(legalEats[j][1])==true)
                    {
                        bd.swap(legalEats[j][0],legalEats[j][2]);
                        bd.setVacant(legalEats[j][1]);
                        rul.addGoat(-1);
                        eat = true;
                        return true;
                    }
                }
            }
        }
        return true;
    }
   
}

标签: javahash2d-gamesmouseclick-event

解决方案


I would start with the // TODO 1, then the // TODO 2, etc. Your unit coordinator put them there for a reason. The assignment builds off the lab-work and lectures you've had throughout the semester. Start with those for some practice if you are unsure of where to start. The assignment should be in pairs so make sure you speak with your partner and bounce ideas off each other.

For more general advice, I'd try start assignments a lot sooner than you seem to have. On top of that, be adviced that your unit coordinators can tell if you have gotten someone else to do your work for you and/or if you've just gotten solutions off the internet.

Sidenote: CITS1001 is the only unit where you'll be using BlueJ.


推荐阅读