我列出了这两种游戏的相似之处,目的是可能将其扩展到国际象棋,但对我的设计提出质疑。
相似点
差异
问题和关切
List<List<Integer>> moves = ((Checker)piece).getPossibleMoves();
备注
我没有完成所有的实现,比如知道玩家什么时候赢了,或者处理边缘案件,或者当一个棋子变成了国王。为了简单起见,我还硬编码了球员的同时,只是想要反馈,如果这是一个好的方向。
java prettyprint-override">public class Piece {
private String marker;
protected int row;
protected int col;
public Piece(String marker, int row, int col) {
this.marker = marker;
this.col = col;
this.row = row;
}
public String getMarker() {
return marker;
}
public void setMarker(String marker) {
this.marker = marker;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
}
public class Player {
private String name;
public Player(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Board {
private Piece[][] grid;
public Board(int rows, int cols) {
grid = new Piece[rows][cols];
}
private boolean isSpotEmpty(int row, int col) {
return grid[row][col] == null;
}
public void move(Piece piece) {
if(isSpotEmpty(piece.getRow(), piece.getCol())) {
grid[piece.getRow()][piece.getCol()] = piece;
} else {
throw new InvalidStateException("Invalid Move");
}
}
public void showBoard() {
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[0].length; j++) {
Piece piece = grid[i][j];
if(piece == null) {
System.out.print('*');
} else {
System.out.print(piece.getMarker());
}
}
System.out.println();
}
}
public boolean isCellEmpty(int row, int col) {
return grid[row][col] == null;
}
public String getMarker(int row, int col) {
return grid[row][col].getMarker();
}
public Piece getPiece(int row, int col) {
return grid[row][col];
}
public void removePiece(int row, int col) {
grid[row][col] = null;
}
}
public abstract class Game {
protected List<Player> players;
protected Board board;
public abstract void startGame();
public abstract Piece getPieceFromInput(Player player, String marker);
}
这是Tic Tac Toe
public class TicTacToe extends Game {
private static final int BOARD_SIZE = 3;
private HashMap<Player, String> playerMap;
public TicTacToe() {
board = new Board(BOARD_SIZE, BOARD_SIZE);
players = new ArrayList<>();
players.add(new Player("player1"));
players.add(new Player("player2"));
playerMap.put(players.get(0), "o");
playerMap.put(players.get(1), "x");
}
@Override
public void startGame() {
boolean playerOneTurn = true;
Player currPlayer;
Piece piece;
while(1 < 2) {
currPlayer = (playerOneTurn) ? players.get(0) : players.get(1);
piece = getPieceFromInput(currPlayer, playerMap.get(currPlayer));
try {
board.move(piece);
playerOneTurn = !playerOneTurn;
} catch(InvalidStateException e) {
System.out.println(currPlayer.getName() + e.getMessage());
}
board.showBoard();
}
}
@Override
public Piece getPieceFromInput(Player player, String marker) {
System.out.println(player.getName() + " Please enter move by row col");
Scanner sc = new Scanner(System.in);
int row = sc.nextInt();
int col = sc.nextInt();
return new Piece(marker, row, col);
}
}
这是跳棋
public abstract class Checker extends Piece implements Movable {
protected Color color;
public Checker(String marker, int row, int col, Color color) {
super(marker, row, col);
this.color = color;
}
}
public enum Color {
RED, BLACK
}
public class King extends Checker {
public King(String marker, int row, int col, Color color) {
super(marker, row, col, color);
}
@Override
public List<List<Integer>> getPossibleMoves() {
List<List<Integer>> list = new ArrayList<>();
//go up/down
for(int i = 0; i < 8; i++) {
if(i == row) continue;
list.add(Arrays.asList(i, col));
}
//go horizontal
for(int i = 0; i < 8; i++) {
if(i == col) continue;
list.add(Arrays.asList(row, i));
}
//go left diag
for(int i = 0; i < 8; i++) {
for(int j = col - row; j < 8; j++) {
if(i == row && j == col) continue;
list.add(Arrays.asList(i, j));
}
}
return list;
}
}
public class Pawn extends Checker {
public Pawn(String marker, int row, int col, Color color) {
super(marker, row, col, color);
}
@Override
public List<List<Integer>> getPossibleMoves() {
List<List<Integer>> list = new ArrayList<>();
if(color == Color.RED) {
list.add(Arrays.asList(row - 1,col - 1));
list.add(Arrays.asList(row - 1,row + 1));
} else {
list.add(Arrays.asList(row + 1,row + 1));
list.add(Arrays.asList(row + 1,row - 1));
}
return list;
}
}
public interface Movable {
List<List<Integer>> getPossibleMoves();
}
public class Checkers extends Game {
private static final int BOARD_SIZE = 8;
private Board board;
private List<Player> players;
private HashMap<Player, String> playerMap;
public Checkers() {
board = new Board(BOARD_SIZE, BOARD_SIZE);
players = new ArrayList<>();
players.add(new Player("alice"));
players.add(new Player("bob"));
playerMap = new HashMap<>();
playerMap.put(players.get(0), "o");
playerMap.put(players.get(1), "x");
}
@Override
public void startGame() {
setBoard();
boolean playerOneTurn = true;
Player currPlayer = null;
String playerMarker = "";
while(1 < 2) {
board.showBoard();
currPlayer = (playerOneTurn) ? players.get(0) : players.get(1);
playerMarker = playerMap.get(currPlayer);
try {
Piece selectedPiece = getPieceFromInput(currPlayer, playerMarker);
setNewPiecePosition(currPlayer, selectedPiece);
playerOneTurn = !playerOneTurn;
} catch(InvalidStateException e) {
System.out.println(e.getMessage());
}
}
}
private void setBoard() {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < BOARD_SIZE; j++) {
if((j + i) % 2 == 0) {
board.move(new Pawn("o", i, j, Color.BLACK));
}
}
}
for(int i = BOARD_SIZE - 1; i > BOARD_SIZE - 4; i--) {
for(int j = 0; j < BOARD_SIZE; j++) {
if((j + i) % 2 == 0) {
board.move(new Pawn("x", i, j, Color.RED));
}
}
}
}
@Override
public Piece getPieceFromInput(Player player, String marker) {
System.out.println(player.getName() + " please select your piece from row : col");
Scanner sc = new Scanner(System.in);
int row = sc.nextInt();
int col = sc.nextInt();
if(board.isCellEmpty(row, col) ) {
throw new InvalidStateException("You selected a wrong piece");
} else if(!board.getMarker(row, col).equals(marker)) {
throw new InvalidStateException("You selected the other players piece");
}
return board.getPiece(row, col);
}
private void setNewPiecePosition(Player player, Piece piece) {
List<List<Integer>> moves = ((Checker)piece).getPossibleMoves();
Scanner sc = new Scanner(System.in);
System.out.println(player.getName() + " Please put your new piece to row : col");
int row = sc.nextInt();
int col = sc.nextInt();
boolean isMoveValid = false;
for(int i = 0; i < moves.size(); i++) {
if(row == moves.get(i).get(0) && col == moves.get(i).get(1)){
isMoveValid = true;
break;
}
}
if(!isMoveValid) {
throw new InvalidStateException("Wrong move for selected piece");
}
board.removePiece(piece.getRow(), piece.getCol());
piece.setRow(row);
piece.setCol(col);
board.move(piece);
}
}
在这里玩游戏
public class GameMain {
public static void main(String[] args) {
Game checkers = new Checkers();
Game tictactoe = new TicTacToe();
checkers.startGame();
tictactoe.startGame();
}
}
在https://gamedev.stackexchange.com/中发布这个问题可能是一个更好的论坛,但这里有一些我的观点,有些可能是错误的,但也许它们会有所帮助(看起来是一个有趣的项目)。
1)我之所以质疑这个设计,是因为我也可以创建一个抽象的方法和一个接口,但这不能扩展到国际象棋。
您可能希望继续使用接口,因为它们允许您以较少的重构来扩展功能,因为您可以实现多个接口,而不是扩展一个接口。如果需要,您还可以使用默认方法包括任何公共代码。
2)我也不知道如何将一个玩家与一个标记(例如在tic tac Toe中的x或o)联系起来。我使用一个hashmap来将一个玩家映射到它的标记。
在分配一个项目给作品的时候,你现在做的并没有什么问题。您可能需要考虑将其做得更好一些,就像piece implements Movable,drawable
(返回到上面的接口注释)。关于棋子的存储位置,如果你想把棋子保存在游戏中,并且让游戏确定每一个棋子的所有可用移动和有效性。或者您可以将它们移到player.Collection中,如果玩家或棋子本身将负责确定棋盘上的可用性。
例如:
public TicTacToe() {
this.players.add(new Player("Player 1", Color.RED, initPieces());
this.players.add(new Player("Player 2", Color.BLACK, initPieces());
}
当玩家控制它的时候,红色会被应用在这个棋子上。例如,如果你有一个游戏,玩家可以偷取其他玩家的代币,向玩家添加新代币的行为会自动更新它的颜色。然后,在根据您正在执行的操作调用piece.draw()、
或piece.draw(canvas)
时应用该颜色。
3)我有一些复选框的代码,我有一个枚举颜色,但我也有一个变量标记,这是一样的东西。不知道如何解决这个问题。
如果使用上面的注释,您可以执行以下操作:
Collection<Piece<String>> initPieces(String mark) {
return Arrays.asList(new Piece<>(mark), ...); // create 5
}
public Person(String name, Color color, Collection<Piece> initialPieces) {
// for initialPieces set piece color to color
}
4)可以对一个对象进行类型化吗?因为board不知道它有什么类型的棋子,所以我必须在Checkers课上这样做
如果你在实现游戏时使用了可移动的界面,那么你就不需要施放了,这两个游戏/游戏板都知道:
List<List<Integer>> moves = piece.getPossibleMoves();
或
this.board = new Board<Checker>();
这将再次确保board.getPeice(x,y)
将返回一个检查器,并且不需要强制转换。这取决于游戏后期可能会发生什么以及规则是什么。
5)基于棋子游戏实现棋子为王的边缘案例。
在大多数游戏中,结果是在移动发生后发生的。例如,正如您所提到的:
在您的跳棋游戏示例中,您需要在处理成功移动的setNewPiecePosition之后调用一些东西。对于跳棋,您需要使用此方法:
本文向大家介绍c# 绘制中国象棋棋盘与棋子,包括了c# 绘制中国象棋棋盘与棋子的使用技巧和注意事项,需要的朋友参考一下 本文是利用C# 实现中国象棋的棋盘绘制,以及初始化布局,并不实现中国象棋的对弈逻辑。仅供学习参考使用。 思路: 绘制中国象棋棋盘,竖线九条,横线十条。再中间绘制‘楚河',‘汉界' 。 绘制棋子,然后将棋子布局在棋盘上即可。 涉及知识点: 用户控件:用于实现棋盘的绘制,重写 OnP
我试图创建象棋游戏,所以我为象棋工具创建抽象类(皇后,国王,车...)我还创建了king工具来检查我的代码: 并创建game_board类: 问题是,当我尝试向矩阵添加对象时,它的show me错误:1 IntelliSense:不允许抽象类类型“King”的对象:纯虚函数“chess_tool::legal_movement”没有覆盖器 ....
相友象棋是一个Andriod游戏,提供让两人用各自的设备在局网内,对下象棋的功能。 相友象棋是相友游戏框架的第一个实现。 相友象棋是一个eclipse工程,并且依赖Node4Android. 它没有android代码,src目录下为空,真正的代码在web目录下,将web目录下的文件打包成web.zip 然后放置于/res/raw目录下,和Node4Android一起生成,才能产生apk
我已经有一个Board对象,包含一个碎片列表。Piece是一个抽象类,有一个位置(x,y)和一个颜色(黑色或白色)。然后是King、Queen、Knight这三个类,实现了Piece类。 谢谢
“在面向对象编程中,抽象是对用户隐藏实现细节的过程,只有功能才会提供给用户。” 我一直在试图理解抽象,有人能告诉我们如何准确地隐藏实现细节吗?使用一个程序
本文向大家介绍C++面向对象实现五子棋小游戏,包括了C++面向对象实现五子棋小游戏的使用技巧和注意事项,需要的朋友参考一下 尽量将面向对象的思想融入进程序中 ChessBoard.h ChessBoard.cpp Player.h Player.cpp main.cpp 以上所述就是本文的全部内容了,希望能够对大家熟练掌握C++有所帮助。