为了巩固类、数组等知识,下来一个Assignment,定睛一看,居然是个四子棋!没想到人在江湖,也会遇上如此困难之题,随缘写个备注以防自己忘记。
完整代码已上传至 timrockefeller/ExplotionEuler。
这次我请到了我在崔斯特姆遇见的朋友,Millie桑!(欢呼、鼓掌)
Millie: 大家好嘿,我是Millie,今天呢很高兴见到大家耶!
对于这个棋局,你怎么看呢?
Millie: 什么棋局?
那个啥、井字棋啊。
Millie: 噢那个我没输过诶~
巧了我也没输过。回归正题,Millie你就坐旁边看就好了。
Millie: 这么没人权吗quq?是你让我过来的诶、
导演开始吧。
构建棋盘
棋盘就用3*3数组表示吧,数组类型可以记为枚举ChessType。
1 2 3 4 5 6
| enum ChessType{ CROSS, CIRCLE, BLANK, NULL }
|
这里分为四种:叉、圈、空、未知。这个“未知”只是用于检测是否越界来着,棋盘之外便是虚空。
接着我们需要写第一个类:Board,它需要完成存储、读写、判断、输出图形这些功能。让Miilie带我们看看这个类的组成部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Board{ public Board (); public Board (ChessType[][] _map); private ChessType[][] map; public ChessType getBoard(Position pos); public boolean setBoard(Position pos,ChessType type); public void setBoardF(Position pos,ChessType type); public void drawBoard(); private String gs(ChessType t); public ChessType judge(); public boolean isFull(); public Board clone(); }
|
Millie: 细节就不放了,其中的Position类:
1 2 3 4 5 6 7 8 9 10
| class Position{ public Position(){ this.x=0;this.y=0; } public Position(int x, int y){ this.x = x;this.y = y; } public int x; public int y; }
|
超简单的,传入pos等变量的时候直接 new Position(x,y)
就好了,当然开发大型游戏的时候它就不能叫Position了,而是Vector2(二维向量),相关函数在MizuhaPic这个写了一半(没有,没有一半,连1%都没有)的游戏引擎里出现过。
Millie: 这个类在后面经常被用到,不停地被克隆,是这个作业、呸游戏的重要成员。以及MizuhaPic怕是要弃坑了。
棋盘有了,我们还需要玩家。玩家分为两类:人和电脑。他们都可以继承于同一个抽象类:Player。
1 2 3 4 5 6 7 8 9
| abstract class Player{ public abstract void onTurn(Board b); public Position hand; public ChessType type; }
|
人类玩家就可以用new Scanner().NextInt()
来获取棋子位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Player_Human extends Player{ public Player_Human(ChessType _type){ this.type= _type; this.hand = new Position(); } @Override public void onTurn(Board b){ this.readInput(); } private void readInput(){ Scanner input = new Scanner (System.in); System.out.print("input x and y (1-3): "); this.hand.x = input.nextInt() - 1; this.hand.y = input.nextInt() - 1; } }
|
那么我们准备好了玩家、棋盘,就需要找个房间来玩,于是我们的老大Game类就来了。同样让Millie为我们解说。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Game { public Game(); private int round; private Board board; private Player[] players = new Player[2]; private int turn; private boolean gaming; private void nextTurn(); private ChessType getTurnType(int _turn); private void run(); private void gameEnd(ChessType type); private void retry(); }
|
巧妙的是这个类只用生成一个对象,也就是传说中的游戏开发设计模式里的单例模式,应该吧。
很棒,一个完整的TicTacToe游戏就完成啦,好好玩玩吧~
以下是未知代码,谨慎阅读!
Millie: 在设计机器人的时候,根本不知道怎么写,好难受、好难受,硬憋憋出一个不明效果的回溯方法。具体就是:检测所有的可走路径Class.Way,保存在**ArrayList**里面,虽然有胜率、败率等权值,但是找不到一个合适的算法解析它们……不管了先来看吧(>^ω^<)
Millie: 在那之前我们需要准备两个类,一个是路径Way,一个是节点Node。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Node{ public Node(){this.p= new Position(0,0);} public Node(Position pos,int i){this.p=pos;this.inspire=i;} public Position p; public int inspire; } class Way { public Way() { this.step = new Node(); } public Way(Node s){ this.step = new Node(new Position(s.p.x, s.p.y), s.inspire); } public int stats; public Node step; @Override public Way clone(){ return new Way(this.step); } }
|
Millie: 好的!结束!我写不懂了……接下来就是战争迷雾模式
1 2 3 4 5 6 7
| class Player_PC extends Player{ public Player_PC (ChessType _type); public void onTurn(Board b); private static ChessType getOppoType(ChessType _type); private ArrayList<Way> ways; private void nextStop(Board b,Way way,int depth,ChessType inType); }
|
Millie: 仔细看看那个nextStop():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| private void nextStop(Board b, Way way, int depth, ChessType inType){ boolean newWay = false; boolean full = true; for(int x = 0; x<3;x++){ for(int y = 0; y<3;y++){ if(b.getBoard(new Position(x,y))==ChessType.BLANK){ full = false; Way _way; if ( newWay ) { _way = way.clone(); this.ways.add(_way); } else { newWay = true; _way = way; } if(depth==0) _way.step=new Node(new Position(x, y), depth); b.setBoardF(new Position(x, y), inType); ChessType wms=b.judge(); if(!b.isFull()) this.nextStop(b.clone(), _way, depth+(wms==ChessType.BLANK?1:0), getOppoType(inType)); else if(wms != ChessType.BLANK) _way.stats=wms==this.type?(10-depth):(depth-10); b.setBoardF(new Position(x,y),ChessType.BLANK); } } } }
|
Millie: 问题是有,但是不知道在哪里quq,难受
Millie: 再您妈的见。