冲刺2

实现5*5的方格

protected void showChooseGameSizeDialog() {
new AlertDialog.Builder(this)
.setNegativeButton( "5 x 5",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
gameView.setGameSize(5);
}
}).show();
}

先把逻辑讲明白

首先跟我们分析对象,以及对象的行为

一共有游戏对象,还有玩家对象

所以我们对类进行拆解

游戏类进行拆解:

Game.java

package com.zzx.apackage.model;

import java.util.ArrayList;
import java.util.Observable;


public class Game extends Observable {
    public Player[] getPlayers() {
        return players;
    }

    private Player[] players;
    private int playerNowIndex;

    public int getWeigh() {
        return weigh;
    }

    public int getHeight() {
        return height;
    }

    private int weigh;
    private int height;
    private Player[][] occupied;
    private boolean[][] horizontalLines;
    private boolean[][] verticalLines;
    private Line latestLine;

    public Line getLatestLine() {
        return latestLine;
    }

    public Game(int weigh, int height, Player firstMover, Player... players) {
        this.weigh = weigh;
        this.height = height;
        this.players = players;

        occupied = new Player[height][weigh];
        horizontalLines = new boolean[height + 1][weigh];
        verticalLines = new boolean[height][weigh + 1];

        this.playerNowIndex = 0;
        for (int i = 0; i < players.length; i++) {
            if (players[i] == null) {
                throw new IllegalArgumentException("Player Is Null");
            }
            if (players[i] == firstMover) {
                playerNowIndex = i;
            }
            players[i].addToGame(this);
        }

        if (players.length == 0)
            throw new IllegalArgumentException("No Player");
        if (weigh < 1 || height < 1)
            throw new IllegalArgumentException("Size Too Small");
    }

    public void start() {
        while (!isGameFinished()) {
            addMove(playerNow().move());//---------------------------------move核心!!!
            setChanged();
            notifyObservers();
        }
    }

    public void addMove(Line move) {
        if (isLineOccupied(move)) {
            return;
        }
        boolean newBoxOccupied = tryToOccupyBox(move);
        setLineOccupied(move);
        latestLine=move;

        if (!newBoxOccupied)
            toNextPlayer();
    }

    public Player playerNow() {
        return players[playerNowIndex];
    }

    public boolean isLineOccupied(Direction direction, int row, int column) {
        return isLineOccupied(new Line(direction, row, column));
    }

    public boolean isLineOccupied(Line line) {
        switch (line.direction()) {
            case HORIZONTAL:
                return horizontalLines[line.row()][line.column()];
            case VERTICAL:
                return verticalLines[line.row()][line.column()];
        }
        throw new IllegalArgumentException(line.direction().toString());
    }

    public Player getBoxOccupier(int row,int column){
        return occupied[row][column];
    }

    public int getPlayerOccupyingBoxCount(Player player) {
        int count=0;
        for(int i=0;i<occupied.length;i++) {
            for (int j = 0; j < occupied[0].length; j++) {
                if(getBoxOccupier(i,j)==player)
                    count++;
            }
        }
        return count;
    }

    private boolean tryToOccupyBox(Line move) {
        boolean rightOccupied = tryToOccupyRightBox(move);
        boolean underOccupied = tryToOccupyUnderBox(move);
        boolean upperOccupied = tryToOccupyUpperBox(move);
        boolean leftOccupied = tryToOccupyLeftBox(move);
        return leftOccupied||rightOccupied||upperOccupied||underOccupied;
    }

    private void setLineOccupied(Line line) {
        switch (line.direction()) {
            case HORIZONTAL:
                horizontalLines[line.row()][line.column()] = true;
                break;
            case VERTICAL:
                verticalLines[line.row()][line.column()] = true;
                break;
        }
    }

    private void setBoxOccupied(int row, int column, Player player) {
        occupied[row][column] = player;
    }

    private boolean tryToOccupyUpperBox(Line move) {
        if (move.direction() != Direction.HORIZONTAL || move.row() <= 0)
            return false;
        if (isLineOccupied(Direction.HORIZONTAL, move.row() - 1, move.column())
                && isLineOccupied(Direction.VERTICAL, move.row() - 1, move.column())
                && isLineOccupied(Direction.VERTICAL, move.row() - 1, move.column() + 1)) {
            setBoxOccupied(move.row() - 1, move.column(), playerNow());
            return true;
        } else {
            return false;
        }
    }

    private boolean tryToOccupyUnderBox(Line move) {
        if (move.direction() != Direction.HORIZONTAL || move.row() >= (height))
            return false;
        if (isLineOccupied(Direction.HORIZONTAL, move.row() + 1, move.column())
                && isLineOccupied(Direction.VERTICAL, move.row(), move.column())
                && isLineOccupied(Direction.VERTICAL, move.row(), move.column() + 1)) {
            setBoxOccupied(move.row(), move.column(), playerNow());
            return true;
        } else {
            return false;
        }
    }

    private boolean tryToOccupyLeftBox(Line move) {
        if (move.direction() != Direction.VERTICAL || move.column() <= 0)
            return false;
        if (isLineOccupied(Direction.VERTICAL, move.row(), move.column() - 1)
                && isLineOccupied(Direction.HORIZONTAL, move.row(), move.column() - 1)
                && isLineOccupied(Direction.HORIZONTAL, move.row() + 1, move.column() - 1)) {
            setBoxOccupied(move.row(), move.column() - 1, playerNow());
            return true;
        } else {
            return false;
        }
    }

    private boolean tryToOccupyRightBox(Line move) {
        if (move.direction() != Direction.VERTICAL || move.column() >= (weigh))
            return false;
        if (isLineOccupied(Direction.VERTICAL, move.row(), move.column() + 1)
                && isLineOccupied(Direction.HORIZONTAL, move.row(), move.column())
                && isLineOccupied(Direction.HORIZONTAL, move.row() + 1, move.column())) {
            setBoxOccupied(move.row(), move.column(), playerNow());
            return true;
        } else {
            return false;
        }
    }

    private void toNextPlayer() {
        playerNowIndex = (playerNowIndex + 1) % players.length;
    }

    private boolean isGameFinished() {
        for (int i = 0; i < occupied.length; i++) {
            for (int j = 0; j < occupied[0].length; j++) {
                 if (occupied[i][j] == null)
                    return false;
            }
        }
        return true;
    }

    public Player[] getWinners() {
        if(!isGameFinished()){
            return null;
        }
        int playerCount = players.length;
        int[] occupyingBoxCount = new int[playerCount];
        int maxOccupyingBoxCount=0;
        for (int player_i = 0; player_i < playerCount; player_i++) {
            occupyingBoxCount[player_i]=getPlayerOccupyingBoxCount(players[player_i]);
            if(occupyingBoxCount[player_i]>maxOccupyingBoxCount)
                maxOccupyingBoxCount=occupyingBoxCount[player_i];
        }
        ArrayList<Player> winners=new ArrayList<>();
        for (int player_i = 0; player_i < playerCount; player_i++) {
            if(occupyingBoxCount[player_i]==maxOccupyingBoxCount){
                winners.add(players[player_i]);
            }
        }
        return winners.toArray(new Player[0]);
    }
}

 

玩家对象分为人还有Ai我们先把他们公共的部分写下来,然后继承一下分别对应写一下

玩家的父类:Player

package com.zzx.apackage.model;


public abstract class Player {
    public abstract Line move();
    private String name;
    private Game game;

    public Game getGame() {
        return game;
    }

    public void addToGame(Game game) {
        this.game = game;
    }


    public Player(String name){
        this.name=name;
    }

    public String getName(){
        return name;
    }

    public static int indexIn(Player player,Player... players){
        for(int i=0;i<players.length;i++){
            if (player==players[i])
                return i;
        }
        return -1;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Player player = (Player) o;

        return !(name != null ? !name.equals(player.name) : player.name != null);

    }

    @Override
    public int hashCode() {
        return name != null ? name.hashCode() : 0;
    }
}

人类玩家:HumanPlayer.java

package com.zzx.apackage.model;

public class HumanPlayer extends Player {
    private Line[] inputBuffer=new Line[1];
    private Object lock=new Object();

    public HumanPlayer(String name) {
        super(name);
    }

    public void add(Line line) {
        synchronized (inputBuffer){
            inputBuffer[0]=line;
            inputBuffer.notify();
        }
    }

    private Line getInput(){
        synchronized (inputBuffer){
            if(inputBuffer[0]!=null){
                Line temp=inputBuffer[0];
                inputBuffer[0]=null;
                return temp;
            }
            try {
                inputBuffer.wait();
            } catch (InterruptedException e) {
            }
            return this.getInput();
        }
    }

    @Override
    public Line move() {
        return getInput();
    }

}

AI玩家:

package com.zzx.apackage.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

public class AIPlayer extends Player {
    private int difficulty;
    private int sz;
    private boolean[][] horizontal;
    private boolean[][] vertical;
    private Box[][] box;
    private Vector<Line> safeLine;
    private Vector<Line> goodLine;
    private Vector<Line> badLine;
    private HashMap<Line, Integer> goodLineValue;
    private HashMap<Line, Integer> badLineValue;
    private HashMap<Line, Integer> goodLineType;

    private AIPlayer(int difficulty, Game game) {
        this(null);
        this.setDifficulty(difficulty);
        this.addToGame(game);
    }

    public void setGameSize(int x){
        sz=x;
    }

    public AIPlayer(String name) {
        super(name);
        horizontal = new boolean[6][5];
        vertical = new boolean[5][6];
        box = new Box[5][5];
        safeLine = new Vector<Line>();
        goodLine = new Vector<Line>();
        badLine = new Vector<Line>();
        badLineValue = new HashMap<Line, Integer>();
        goodLineValue = new HashMap<Line, Integer>();
        goodLineType = new HashMap<Line, Integer>();

    }

    public void setDifficulty(int difficulty) {
        this.difficulty = difficulty;
    }

    public Line move() {
        initialiseBoard();
        initialiseSafeLine();
        initialiseGoodLine();
        initialiseBadLine();

        if (difficulty <= 1) {
            return normal();
        } else if (difficulty == 2) {
            return hard();
        } else if (difficulty >= 3) {
            return ultra();
        } else
            return random();
    }

    private void initialiseGoodLine() {
        int counter = 0;
        boolean t1 = false;
        boolean t2 = false;
        goodLine.clear();
        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                if (!horizontal[i][j]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (box[i][j].contain() == 3)
                            goodLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else if (i == sz) {

                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter == 3)
                            goodLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (counter == 3)
                            t1 = true;
                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter == 3)
                            t2 = true;
                        if (t1 || t2)
                            goodLine.add(new Line(Direction.HORIZONTAL, i, j));
                        t1 = false;
                        t2 = false;
                    }
                }
                if (!vertical[j][i]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter == 3)
                            goodLine.add(new Line(Direction.VERTICAL, j, i));
                    } else if (i == sz) {
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter == 3)
                            goodLine.add(new Line(Direction.VERTICAL, j, i));
                    } else {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter == 3)
                            t1 = true;
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter == 3)
                            t2 = true;
                        if (t1 || t2)
                            goodLine.add(new Line(Direction.VERTICAL, j, i));
                        t1 = false;
                        t2 = false;
                    }
                }
            }
        }

    }

    private void initialiseBadLine() {
        int counter = 0;
        boolean t1 = false;
        boolean t2 = false;
        badLine.clear();
        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                if (!horizontal[i][j]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (counter == 2)
                            badLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else if (i == sz) {

                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter == 2)
                            badLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (counter == 2)
                            t1 = true;
                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter == 2)
                            t2 = true;
                        if (t1 || t2)
                            badLine.add(new Line(Direction.HORIZONTAL, i, j));
                        t1 = false;
                        t2 = false;
                    }
                }
                if (!vertical[j][i]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter == 2)
                            badLine.add(new Line(Direction.VERTICAL, j, i));
                    } else if (i == sz) {
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter == 2)
                            badLine.add(new Line(Direction.VERTICAL, j, i));
                    } else {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter == 2)
                            t1 = true;
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter == 2)
                            t2 = true;
                        if (t1 || t2)
                            badLine.add(new Line(Direction.VERTICAL, j, i));
                        t1 = false;
                        t2 = false;
                    }
                }
            }
        }
        for (Line a : goodLine) {
            try {
                for (Line b : badLine) {
                    if (a.direction() == b.direction() && a.row() == b.row() && a.column() == b.column()) {
                        badLine.remove(b);
                    }
                }
            } catch (Exception e) {
            }
        }
    }

    private void initialiseSafeLine() {
        int counter = 0;
        boolean t1 = false;
        boolean t2 = false;
        safeLine.clear();

        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                if (!horizontal[i][j]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (counter < 2)
                            safeLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else if (i == sz) {

                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter < 2)
                            safeLine.add(new Line(Direction.HORIZONTAL, i, j));
                    } else {
                        counter = 0;
                        if (box[i][j].left)
                            counter++;
                        if (box[i][j].bottom)
                            counter++;
                        if (box[i][j].right)
                            counter++;
                        if (counter < 2)
                            t1 = true;
                        counter = 0;
                        if (box[i - 1][j].left)
                            counter++;
                        if (box[i - 1][j].top)
                            counter++;
                        if (box[i - 1][j].right)
                            counter++;
                        if (counter < 2)
                            t2 = true;
                        if (t1 && t2)
                            safeLine.add(new Line(Direction.HORIZONTAL, i, j));
                        t1 = false;
                        t2 = false;
                    }
                }
                if (!vertical[j][i]) {
                    if (i == 0) {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter < 2)
                            safeLine.add(new Line(Direction.VERTICAL, j, i));
                    } else if (i == sz) {
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter < 2)
                            safeLine.add(new Line(Direction.VERTICAL, j, i));
                    } else {
                        counter = 0;
                        if (box[j][i].right)
                            counter++;
                        if (box[j][i].bottom)
                            counter++;
                        if (box[j][i].top)
                            counter++;
                        if (counter < 2)
                            t1 = true;
                        counter = 0;
                        if (box[j][i - 1].left)
                            counter++;
                        if (box[j][i - 1].top)
                            counter++;
                        if (box[j][i - 1].bottom)
                            counter++;
                        if (counter < 2)
                            t2 = true;
                        if (t1 && t2)
                            safeLine.add(new Line(Direction.VERTICAL, j, i));
                        t1 = false;
                        t2 = false;
                    }
                }
            }
        }
    }

    private void initialiseBoard() {
        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                if (getGame().isLineOccupied(Direction.HORIZONTAL, i, j))
                    horizontal[i][j] = true;
                else
                    horizontal[i][j] = false;
                if (getGame().isLineOccupied(Direction.VERTICAL, j, i))
                    vertical[j][i] = true;
                else
                    vertical[j][i] = false;
            }
        }
        for (int i = 0; i < sz; i++) {
            for (int j = 0; j < sz; j++) {
                box[i][j] = new Box(vertical[i][j], horizontal[i][j],
                        vertical[i][j + 1], horizontal[i + 1][j]);
            }
        }
    }

    private void initialiseGoodLineValue() {
        if (goodLine.isEmpty())
            return;
        goodLineValue.clear();
        for (Line Line : goodLine) {
            VBoard vboard = new VBoard(horizontal, vertical);
            goodLineValue.put(Line, vboard.getGoodLineValue(Line));
        }
    }

    private void initialiseBadLineValue() {
        if (badLine.isEmpty())
            return;
        badLineValue.clear();
        for (Line Line : badLine) {
            VBoard vboard = new VBoard(horizontal, vertical);
            badLineValue.put(Line, vboard.getBadLineValue(Line));
        }
    }

    private void initialiseGoodLineType() {
        if (goodLine.isEmpty())
            return;
        goodLineType.clear();
        for (Line Line : goodLine) {
            if (Line.direction() == Direction.HORIZONTAL) {
                if (Line.row() == 0)
                    goodLineType.put(Line, 1);
                else if (Line.row() == sz)
                    goodLineType.put(Line, 1);
                else {
                    int counter = 0;
                    if (box[Line.row()][Line.column()].contain() == 3)
                        counter++;
                    if (box[Line.row() - 1][Line.column()].contain() == 3)
                        counter++;
                    goodLineType.put(Line, counter);
                }
            } else {
                if (Line.column() == 0)
                    goodLineType.put(Line, 1);
                else if (Line.column() == sz)
                    goodLineType.put(Line, 1);
                else {
                    int counter = 0;
                    if (box[Line.row()][Line.column()].contain() == 3)
                        counter++;
                    if (box[Line.row()][Line.column() - 1].contain() == 3)
                        counter++;
                    goodLineType.put(Line, counter);
                }

            }

        }
    }

    private Line Line(VBoard vboard) {
        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                horizontal[i][j] = vboard.horizontal[i][j];
                vertical[j][i] = vboard.vertical[j][i];
            }
        }
        for (int i = 0; i < sz; i++) {
            for (int j = 0; j < sz; j++) {
                box[i][j] = new Box(vertical[i][j], horizontal[i][j],
                        vertical[i][j + 1], horizontal[i + 1][j]);
            }
        }
        initialiseSafeLine();
        initialiseGoodLine();
        initialiseBadLine();

        if (difficulty == 1) {
            return normal();
        } else if (difficulty == 2) {
            return hard();
        } else if (difficulty == 3) {
            return ultra();
        } else
            return random();
    }

    private Line normal() {
        if (goodLine.size() != 0)
            return goodLine.get((int) ((goodLine.size()) * Math.random()));
        if (safeLine.size() != 0)
            return safeLine.get((int) ((safeLine.size()) * Math.random()));
        else {
            Line min = null;
            int minValue = 26;
            initialiseBadLineValue();
            for (Line Line : badLine) {
                if (badLineValue.get(Line) < minValue) {
                    min = Line;
                    minValue = badLineValue.get(Line);
                }
            }
            return min;
        }
    }

    private Line hard() {
        if (safeLine.size() != 0) {
            if (goodLine.size() != 0)
                return goodLine.get((int) ((goodLine.size()) * Math.random()));
            else
                return safeLine.get((int) ((safeLine.size()) * Math.random()));
        }
        else if (goodLine.size() != 0) {
            if (badLine.size() == 0)//可以通吃结束战斗,直接下
                return goodLine.get((int) ((goodLine.size()) * Math.random()));
            initialiseGoodLineValue();
            initialiseBadLineValue();

            ArrayList<Line> bad = new ArrayList<Line>();
            ArrayList<Line> bad2 = new ArrayList<Line>();
            ArrayList<Line> good = new ArrayList<Line>();
            ArrayList<Line> good2 = new ArrayList<Line>();
            int badValue = 26;
            int bad2Value = 26;
            int goodValue = 0;//这步最多占领多少格
            int goodValue2 = 0;//这步倒数第二多占领多少格

            for (Line Line : badLine) {
                if (badLineValue.get(Line) < badValue) {
                    bad2.clear();
                    for (Line m : bad) {
                        bad2.add(m);
                    }
                    bad2Value = badValue;
                    bad.clear();
                    bad.add(Line);
                    badValue = badLineValue.get(Line);
                } else if (badLineValue.get(Line) == badValue) {
                    bad.add(Line);
                }
            }
            for (Line Line : goodLine) {
                if (goodLineValue.get(Line) > goodValue) {
                    good2.clear();
                    for (Line m : good) {
                        good2.add(m);
                    }
                    goodValue2 = goodValue;
                    good.clear();
                    good.add(Line);
                    goodValue = goodLineValue.get(Line);
                } else if (goodLineValue.get(Line) == goodValue) {
                    good.add(Line);
                }
            }

            //AI灵魂,留给对方两个子,自己拿剩下的一条
            if (goodValue == 2 && badValue == 2 && bad.size() == 1 && bad2.size() != 0 && bad2Value > 6) {
                if (goodValue2 > 2) {
                    return good2.get((int) ((good2.size()) * Math.random()));
                }
                initialiseGoodLineType();
                for (Line Line : good) {
                    if (goodLineType.get(Line) == 2) {
                        return Line;
                    }
                }
                return bad.get(0);
            }

            else{
                return good.get((int) ((good.size()) * Math.random()));
            }

        }
        else {
            Line min = null;
            int minValue = 26;
            initialiseBadLineValue();
            for (Line Line : badLine) {
                if (badLineValue.get(Line) < minValue) {
                    min = Line;
                    minValue = badLineValue.get(Line);
                }
            }
            return min;
        }

    }

    private Line ultra() {
        if (safeLine.size() != 0) {
            if (goodLine.size() != 0)
                return goodLine.get((int) ((goodLine.size()) * Math.random()));
            else
                return safeLine.get((int) ((safeLine.size()) * Math.random()));
        } else if (goodLine.size() != 0) {
            if (badLine.size() == 0)
                return goodLine.get((int) ((goodLine.size()) * Math.random()));
            initialiseGoodLineValue();
            initialiseBadLineValue();

            ArrayList<Line> bad = new ArrayList<Line>();
            ArrayList<Line> bad2 = new ArrayList<Line>();
            ArrayList<Line> good = new ArrayList<Line>();
            ArrayList<Line> good2 = new ArrayList<Line>();
            int badValue = 26;
            int bad2Value = 26;
            int goodValue = 0;
            int goodValue2 = 0;
            for (Line Line : badLine) {
                if (badLineValue.get(Line) < badValue) {
                    bad2.clear();
                    for (Line m : bad) {
                        bad2.add(m);
                    }
                    bad2Value = badValue;
                    bad.clear();
                    bad.add(Line);
                    badValue = badLineValue.get(Line);
                } else if (badLineValue.get(Line) == badValue) {
                    bad.add(Line);
                }
            }
            for (Line Line : goodLine) {
                if (goodLineValue.get(Line) > goodValue) {
                    good2.clear();
                    for (Line m : good) {
                        good2.add(m);
                    }
                    goodValue2 = goodValue;
                    good.clear();
                    good.add(Line);
                    goodValue = goodLineValue.get(Line);
                } else if (goodLineValue.get(Line) == goodValue) {
                    good.add(Line);
                }
            }

            if (goodValue == 2 && badValue == 2 && bad.size() == 1
                    && bad2.size() != 0 && bad2Value > 6) {
                if (goodValue2 > 2) {
                    return good2.get((int) ((good2.size()) * Math.random()));
                }
                initialiseGoodLineType();
                for (Line Line : good) {
                    if (goodLineType.get(Line) == 2) {
                        return Line;
                    }
                }
                return bad.get(0);
            } else
                return good.get((int) ((good.size()) * Math.random()));

        } else {
            Line min = null;
            int minValue = 26;
            initialiseBadLineValue();
            for (Line Line : badLine) {
                if (badLineValue.get(Line) < minValue) {
                    min = Line;
                    minValue = badLineValue.get(Line);
                }
            }
            return min;
        }

    }

    private Line random() {
        if (goodLine.size() != 0)
            return goodLine.get((int) ((goodLine.size()) * Math.random()));
        Line line=null;
        for (int i = 0; i < sz+1; i++) {
            for (int j = 0; j < sz; j++) {
                if (!horizontal[i][j]) {
                    line = new Line(Direction.HORIZONTAL, i, j);
                    break;
                }
                if (!vertical[j][i]) {
                    line = new Line(Direction.VERTICAL, j, i);
                    break;
                }
            }
        }
        return line;
    }

    private static class Box {
        boolean left;
        boolean top;
        boolean right;
        boolean bottom;
        boolean ocpd;

        Box(boolean l, boolean t, boolean r, boolean b) {
            this.left = l;
            this.top = t;
            this.right = r;
            this.bottom = b;
            if (l && t && r && b)
                this.ocpd = true;
            else
                this.ocpd = false;
        }

        int contain() {
            int counter = 0;
            if (this.left)
                counter++;
            if (this.right)
                counter++;
            if (this.top)
                counter++;
            if (this.bottom)
                counter++;
            return counter;
        }

    }

    class VBoard {
        boolean[][] horizontal;
        boolean[][] vertical;
        boolean[][] occupied;
        boolean keepgoing;
        private Box[][] box;

        VBoard(boolean[][] h, boolean[][] v) {
            horizontal = new boolean[6][5];
            vertical = new boolean[5][6];
            occupied = new boolean[5][5];
            box = new Box[5][5];
            for (int i = 0; i < sz+1; i++) {
                for (int j = 0; j < sz; j++) {
                    horizontal[i][j] = h[i][j];
                    vertical[j][i] = v[j][i];
                }
            }

        }

        void ini() {
            for (int i = 0; i < sz; i++) {
                for (int j = 0; j < sz; j++) {
                    box[i][j] = new Box(vertical[i][j], horizontal[i][j],
                            vertical[i][j + 1], horizontal[i + 1][j]);
                    if (box[i][j].ocpd)
                        occupied[i][j] = true;
                }
            }
        }

        void add(Line Line) {
            Direction type = Line.direction();
            int a = Line.row();
            int b = Line.column();
            keepgoing = false;

            switch (type) {
                case HORIZONTAL:
                    if (!horizontal[a][b]) {
                        horizontal[a][b] = true;
                        if (a == 0) {
                            if (horizontal[a + 1][b] && vertical[a][b]
                                    && vertical[a][b + 1]) {
                                occupied[a][b] = true;
                                keepgoing = true;
                            }
                        } else if (a == sz) {
                            if (horizontal[a - 1][b] && vertical[a - 1][b]
                                    && vertical[a - 1][b + 1]) {
                                occupied[a - 1][b] = true;
                                keepgoing = true;
                            }
                        } else {
                            if (horizontal[a + 1][b] && vertical[a][b]
                                    && vertical[a][b + 1]) {
                                occupied[a][b] = true;
                                keepgoing = true;
                            }
                            if (horizontal[a - 1][b] && vertical[a - 1][b]
                                    && vertical[a - 1][b + 1]) {
                                occupied[a - 1][b] = true;
                                keepgoing = true;
                            }
                        }
                    } else {
                        keepgoing = true;
                    }
                    break;
                case VERTICAL:
                    if (!vertical[a][b]) {
                        vertical[a][b] = true;
                        if (b == 0) {
                            if (vertical[a][b + 1] && horizontal[a][b]
                                    && horizontal[a + 1][b]) {
                                occupied[a][b] = true;
                                keepgoing = true;
                            }
                        } else if (b == sz) {
                            if (vertical[a][b - 1] && horizontal[a][b - 1]
                                    && horizontal[a + 1][b - 1]) {
                                occupied[a][b - 1] = true;
                                keepgoing = true;
                            }
                        } else {
                            if (vertical[a][b + 1] && horizontal[a][b]
                                    && horizontal[a + 1][b]) {
                                occupied[a][b] = true;
                                keepgoing = true;
                            }
                            if (vertical[a][b - 1] && horizontal[a][b - 1]
                                    && horizontal[a + 1][b - 1]) {
                                occupied[a][b - 1] = true;
                                keepgoing = true;
                            }
                        }
                    } else {
                        keepgoing = true;
                    }
                    break;
            }
        }

        int getOccupiedNumber() {
            int counter = 0;
            for (int i = 0; i < sz; i++) {
                for (int j = 0; j < sz; j++) {
                    if (occupied[i][j])
                        counter++;
                }
            }
            return counter;
        }

        int getBadLineValue(Line Line) {
            int start, end;
            if (Line.direction() == Direction.HORIZONTAL)
                this.horizontal[Line.row()][Line.column()] = true;
            else
                this.vertical[Line.row()][Line.column()] = true;
            AIPlayer ai = new AIPlayer(0, getGame());
            ai.setGameSize(sz);
            ini();
            start = this.getOccupiedNumber();
            keepgoing = true;
            while (keepgoing) {
                add(ai.Line(this));
                if (sz==5&&this.getOccupiedNumber() == 25||sz==3&&this.getOccupiedNumber()==9)
                    break;
            }
            end = this.getOccupiedNumber();
            return (end - start);
        }

        int getGoodLineValue(Line Line) {
            int start, end;
            if (Line.direction() == Direction.HORIZONTAL)
                this.horizontal[Line.row()][Line.column()] = true;
            else
                this.vertical[Line.row()][Line.column()] = true;
            AIPlayer ai = new AIPlayer(0, getGame());
            ai.setGameSize(sz);
            ini();
            start = this.getOccupiedNumber();
            keepgoing = true;
            while (keepgoing) {
                add(ai.Line(this));
                if (sz==5&&this.getOccupiedNumber() == 25||sz==3&&this.getOccupiedNumber()==9)
                    break;
            }
            end = this.getOccupiedNumber();
            return (end - start);
        }
    }

}

 

 

对应的前端逻辑界面

Game.java

package com.zzx.apackage.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.zzx.apackage.model.Direction;
import com.zzx.apackage.model.Line;

import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;

import com.zzx.apackage.model.Direction;
import com.zzx.apackage.model.Game;
import com.zzx.apackage.model.HumanPlayer;
import com.zzx.apackage.model.Line;
import com.zzx.apackage.model.Player;

@SuppressLint("ClickableViewAccessibility")
public class GameView extends View implements Observer {
    protected static int SIZE=3;
    protected static float ENLARGE=(float)39/24 ;

    protected static float radius = (float) 14 / 824 ;
    protected static float start = (float) 6 / 824 *ENLARGE;
    protected static float stop = (float) 819 / 824 ;
    protected static float add1 = (float) 18 / 824 *ENLARGE;
    protected static float add2 = (float) 2 / 824 *ENLARGE;
    protected static float add3 = (float) 14 / 824 *ENLARGE;
    protected static float add4 = (float) 141 / 824 *ENLARGE;
    protected static float add5 = (float) 159 / 824 *ENLARGE;
    protected static float add6 = (float) 9 / 824 *ENLARGE;

    protected static final int[] playerColors = new int[]{0xFF6C69FF, 0x88E5004F};
    public static final int GRAY = 0xFF666666;
    protected Game game;
    protected Line move;
    protected Paint paint;
    protected int viewWidth;
    protected int viewHeight;
    protected PlayersStateView playersState;

    public GameView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        paint = new Paint();
        paint.setAntiAlias(true);
        this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                playersState.playerTouched();//放不放歌
                receiveInput(event);
                return false;
            }
        });
    }

    public void setGameSize(int x){
        if(x==3){
            SIZE=3;
            ENLARGE=(float) 39/24;
        }else{
            SIZE=5;
            ENLARGE=1;
        }
        radius = (float) 14 / 824 ;
        start = (float) 6 / 824 *ENLARGE;
        stop = (float) 819 / 824 ;
        add1 = (float) 18 / 824 *ENLARGE;
        add2 = (float) 2 / 824 *ENLARGE;
        add3 = (float) 14 / 824 *ENLARGE;
        add4 = (float) 141 / 824 *ENLARGE;
        add5 = (float) 159 / 824 *ENLARGE;
        add6 = (float) 9 / 824 *ENLARGE;
    }

    public Game getGame() {
        return game;
    }

    public void setPlayersState(PlayersStateView playersState) {
        this.playersState = playersState;
    }

    public void startGame(Player firstMover, Player... players) {
        game = new Game(SIZE, SIZE, firstMover, players);//------------5X5

        game.addObserver(this);
        new Thread() {
            @Override
            public void run() {
                game.start();
            }
        }.start();//------------------------------------------------------------------------!!!!!!
        invalidate();//重绘
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (game == null)
            return;
        canvas.drawColor(0x00FFFFFF);
        viewWidth = this.getWidth();
        viewHeight = this.getHeight();
        int min = Math.min(viewWidth, viewHeight);
        float radius = GameView.radius * min;
        float start = GameView.start * min;
        float stop = GameView.stop * min;
        float add1 = GameView.add1 * min;
        float add2 = GameView.add2 * min;
        float add4 = GameView.add4 * min;
        float add5 = GameView.add5 * min;
        float add6 = GameView.add6 * min;

//        //外边框线
        paint.setColor(playerNowColor());
        float temp = add2 / 2;
        for (int i = 1; i < 6; i++) {
            canvas.drawLine(temp * i, temp * i, min - temp * (i - 1), temp * i, paint);
            canvas.drawLine(temp * i, temp * i, temp * i, min - temp * (i - 1), paint);
            canvas.drawLine(min - temp * (i - 1), temp * i, min - temp * (i - 1), min - temp * (i - 1), paint);
            canvas.drawLine(temp * i, min - temp * (i - 1), min - temp * (i - 1), min - temp * (i - 1), paint);
        }
//
//        //内边框线
        paint.setColor(0xFF777777);
        for (int i = 0; i < 6; i++) {
            canvas.drawLine(start + add5 * i, start, start + add5 * i, stop,
                    paint);
            canvas.drawLine(start + add5 * i + add1, start, start + add5 * i
                    + add1, stop, paint);
            canvas.drawLine(start, start + add5 * i, stop, start + add5 * i,
                    paint);
            canvas.drawLine(start, start + add5 * i + add1, stop, start + add5
                    * i + add1, paint);
        }

        //60条线
        paint.setColor(0xFF000000);
        for (int i = 0; i < SIZE+1; i++) {
            for (int j = 0; j < SIZE; j++) {//------------------------------------------------5X5
                Line horizontal = new Line(Direction.HORIZONTAL, i, j);
                if (horizontal.equals(game.getLatestLine())) {
                    paint.setColor(0xFFFF7700);
                } else if (game.isLineOccupied(horizontal)) {
                    paint.setColor(0xFF000000);
                } else {
                    paint.setColor(0xFFFFFFFF);
                }
                canvas.drawRect(start + add5 * j + add1, start + add5 * i
                        + add2, start + add5 * (j + 1), start + add5 * i + add1 - add2, paint);

                Line vertical = new Line(Direction.VERTICAL, j, i);
                if (vertical.equals(game.getLatestLine())) {
                    paint.setColor(0xFFFF7700);
                } else if (game.isLineOccupied(vertical)) {
                    paint.setColor(0xFF000000);
                } else {
                    paint.setColor(0xFFFFFFFF);
                }
                canvas.drawRect(start + add5 * i + add2, start + add5 * j
                        + add1, start + add5 * i + add1 - add2, start + add5
                        * (j + 1), paint);
            }
        }

        //占领的格子
        for (int i = 0; i < game.getWeigh(); i++) {
            for (int j = 0; j < game.getHeight(); j++) {
                paint.setColor(game.getBoxOccupier(j, i) == null ? Color.TRANSPARENT : playerColors[Player.indexIn(game.getBoxOccupier(j, i), game.getPlayers())]);
                canvas.drawRect(start + add5 * i + add1 + add2, start
                        + add5 * j + add1 + add2, start + add5 * i + add1
                        + add4 - add2, start + add5 * j + add1 + add4
                        - add2, paint);
            }
        }

//        //
        paint.setColor(GRAY);
        for (int i = 0; i < SIZE+1; i++) {
            for (int j = 0; j < SIZE+1; j++) {
                canvas.drawCircle(start + add6 + j * add5 + 1, start + add6 + i
                        * add5 + 1, radius, paint);
            }
        }
    }

    //接收触碰,生成Line
    private void receiveInput(MotionEvent event) {
        if (event.getAction() != MotionEvent.ACTION_DOWN)
            return;
        if (!(game.playerNow() instanceof HumanPlayer)) {
            return;
        }
        float touchX = event.getX();
        float touchY = event.getY();
        int min = Math.min(viewWidth, viewHeight);
        float start = GameView.start * min;
        float add1 = GameView.add1 * min;
        float add2 = GameView.add2 * min;
        float add3 = GameView.add3 * min;
        float add5 = GameView.add5 * min;
        int d = -1, a = -1, b = -1;
        for (int i = 0; i < SIZE+1; i++) {
            for (int j = 0; j < SIZE; j++) {//-----------------------------5X5
                if ((start + add5 * j + add1 - add3) <= touchX
                        && touchX <= (start + add5 * (j + 1) + add3)
                        && touchY >= start + add5 * i + add2 - add3
                        && touchY <= start + add5 * i + add1 - add2 + add3) {
                    d = 0;
                    a = i;
                    b = j;
                }
                if (start + add5 * i + add2 - add3 <= touchX
                        && touchX <= start + add5 * i + add1 - add2 + add3
                        && touchY >= start + add5 * j + add1 - add3
                        && touchY <= start + add5 * (j + 1) + add3) {
                    d = 1;
                    a = j;
                    b = i;
                }
            }
        }

        if (a != -1 && b != -1 && d != -1) {
            Direction direction;
            if (d == 0)
                direction = Direction.HORIZONTAL;
            else
                direction = Direction.VERTICAL;
            move = new Line(direction, a, b);
            ((HumanPlayer) game.playerNow()).add(move);

        }
    }

    @Override
    public void update(Observable observable, Object data) {
        invalidate();
        playersState.setPlayerNow(game.playerNow());
        Map<Player, Integer> player_occupyingBoxCount_map = new HashMap<>();
        for (Player player : game.getPlayers()) {
            player_occupyingBoxCount_map.put(player, game.getPlayerOccupyingBoxCount(player));
        }
        playersState.setPlayerOccupyingBoxesCount(player_occupyingBoxCount_map);

        Player[] winners = game.getWinners();
        if (winners != null) {
            playersState.setWinner(winners);
        }
    }

    private int playerNowColor() {
        int playerIndex = Player.indexIn(game.playerNow(), game.getPlayers());
        return playerIndex == -1 ? Color.BLACK : playerColors[playerIndex];
    }
}

 

MainActivty.java

package com.zzx.apackage.view;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.zzx.apackage.R;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Intent doubleee=new Intent(this,DoubleActivity.class);
        final Intent helpp=new Intent(this,HelpActivity.class);
        final Intent singlee=new Intent(this,SingleActivity.class);
        final Intent sound=new Intent(this,SoundSettingActivity.class);
        Button single= (Button) findViewById(R.id.imageButton2);
        Button doublee=(Button)findViewById(R.id.imageButton3);
        Button help=(Button)findViewById(R.id.imageButton6);
        Button soundd=(Button)findViewById(R.id.imageButton1);
        
        soundd.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                startActivity(sound);
            }
        });
        doublee.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                startActivity(doubleee);
            }
        });
        help.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                startActivity(helpp);
            }
        });
        single.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                startActivity(singlee);
            }
        });
    }

    static long firstTime=0;
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK){
            long secondTime=System.currentTimeMillis();
            if(secondTime-firstTime>2000){
                Toast.makeText(MainActivity.this,"zzx提醒您,再按一次退出程序",Toast.LENGTH_SHORT).show();
                firstTime=secondTime;
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }

}

 

SingActivity.java

package com.zzx.apackage.view;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

import com.zzx.apackage.R;

import com.zzx.apackage.model.AIPlayer;
import com.zzx.apackage.model.HumanPlayer;
import com.zzx.apackage.model.Player;

public class SingleActivity extends DoubleActivity {
    private AIPlayer computer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView player2name = (TextView) findViewById(R.id.player2name);
        player2name.setText("电脑");
        player2name.setText("Computer");
        ImageView player2picture = (ImageView) findViewById(R.id.player2picture);
        player2picture.setImageResource(R.mipmap.computer);

        showChooseAIDifficultyDialog();
    }

    @Override
    protected Player[] initPlayers() {
        computer = new AIPlayer("电脑");
        return new Player[]{new HumanPlayer("玩家一"), computer};
    }

    @Override
    protected void showChooseGameSizeDialog() {
        new AlertDialog.Builder(this)
                .setTitle("点线棋")
                .setMessage("请选择棋盘大小")
                .setPositiveButton("3 x 3",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int which) {
                                gameView.setGameSize(3);
                                computer.setGameSize(3);
                            }
                        })
                .setNegativeButton( "5 x 5",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int which) {
                                gameView.setGameSize(5);
                                computer.setGameSize(5);
                            }
                        }).show();
    }

    private void showChooseAIDifficultyDialog() {
        new AlertDialog.Builder(this)
                .setTitle("点线棋")
                .setMessage("选择难度")
                .setPositiveButton("普通",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int which) {
                                computer.setDifficulty(1);
                            }
                        })
                .setNeutralButton("困难", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        computer.setDifficulty(2);
                    }
                })
                .setNegativeButton("地狱",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int which) {
                                computer.setDifficulty(3);
                            }
                        }).show();
    }

}

对应的线的对象:

Line.java

package com.zzx.apackage.model;

public class Line {
    private final Direction direction;
    private final int row;
    private final int column;

    public Line(Direction direction, int row, int column) {
        this.direction = direction;
        this.row = row;
        this.column = column;
    }

    public Direction direction() {
        return direction;
    }

    public int row() {
        return row;
    }

    public int column() {
        return column;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Line line = (Line) o;

        if (row != line.row) return false;
        if (column != line.column) return false;
        return direction == line.direction;

    }

    @Override
    public int hashCode() {
        int result = direction != null ? direction.hashCode() : 0;
        result = 31 * result + row;
        result = 31 * result + column;
        return result;
    }

    @Override
    public String toString() {
        return "direction:"+direction().toString()+"row:"+row+"column"+column;
    }
}

 

posted @ 2022-06-13 21:45  秃头crazy  阅读(30)  评论(0)    收藏  举报