冲刺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; } }

浙公网安备 33010602011771号