Triển khai Snakes and Ladders đơn giản trong Java
Tôi đã tạo ra một triển khai rắn và thang khá thẳng về phía trước trong Java chỉ cho cái quái của nó. Chương trình có thể được tóm tắt là-
Object of Board chứa một mảng Type Tile để đại diện cho bảng thực tế.
Đối tượng kiểu Tile chứa một thành viên dữ liệu Enum để xác định xem nó là một ô thông thường hay một con rắn / bậc thang.
Cũng chứa một ô đích để xác định điểm đến con rắn / bậc thang.
Đối tượng người chơi chứa tên người chơi và vị trí người chơi.
Khi khởi tạo, thông qua các ngẫu nhiên, tôi tạo ra các ô ngẫu nhiên để làm rắn và thang. Sau đó, người dùng được yêu cầu nhập không. của người chơi, và sau đó tiếp tục tung xúc xắc cho đến khi người chơi đạt đến ô thứ 100.
Mật mã:
Lớp BoardImpl:
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BoardImpl implements Board{
Tile[] board = new Tile[101]; //A array to represent the 'board'
List<Player> players = new ArrayList<>();
SecureRandom secureRandom = new SecureRandom();
Set<Integer> occupiedPositions = new HashSet<>();
public void setPlayers(List<Player> players) {
this.players = players;
}
public Tile[] getBoard() {
return board;
}
public List<Player> getPlayers() {
return players;
}
public void addPlayers(Player player) {
this.players.add(player);
}
@Override
public void initialize() {
//this function generates the board, placing random snakes and ladders and
//filling the rest with normal tiles
System.out.println("Initializing board");
int snakes = secureRandom.nextInt(15) + 1; //generates snakes &
int ladders = secureRandom.nextInt(15) + 1; //ladders at random
//positions
setSnakes(snakes);
setLadders(ladders);
for(int i = 0; i < 101; i++){
if(board[i] != null){
continue;
}
Tile t = new TileImpl(TileType.NORMAL);
board[i] = t;
}
}
@Override
public void movePlayer(Player player, int places) {
int currentPosition = player.getPosition();
String checkPos = checkEndingPosition(currentPosition, places);
if(checkPos.equals("winner")){
winner(player);
}
if(checkPos.equals("outOfBoard")){
System.out.println("That move cannot be made from your position! " +
"Roll a different number next time");
}
if(checkPos.equals("valid")){
Tile t = getTile(currentPosition + places);
if(t.getType().equals(TileType.NORMAL)){
player.setPosition(currentPosition + places);
System.out.println("Player " + player.getName() +
" moves to position "+ player.getPosition());
}else {
player.setPosition(t.getDestination());
System.out.println(" Player " + player.getName() +
" encountered a "+ t.getType()+ "!!, moves to position "+ player.getPosition());
}
}
}
@Override
public Tile getTile(int n) {
return board[n];
}
public String checkEndingPosition(int currentPosition, int places){
if((currentPosition + places) > 100){
return "outOfBoard";
}else if((currentPosition+ places) == 100){
return "winner";
}
else{
return "valid";
}
}
public void winner(Player player){
System.out.print("Player " + player.getName() + " has won the game !");
System.exit(0);
}
public void setSnakes(int n){
//this function generates snakes at random positions
for(int i = 0; i < n; i ++){
boolean flag = true;
int start = 0;
int dest = 0;
while(flag) {
start = secureRandom.nextInt(98);
if(!occupiedPositions.contains(start)){
occupiedPositions.add(start);
break;
}
}
while(flag) {
//Setting the destination for a snake tile to lower than its position
dest = (int)(start * secureRandom.nextDouble());
if(!occupiedPositions.contains(dest)){
occupiedPositions.add(dest);
break;
}
}
Tile tile = new TileImpl(TileType.SNAKE, dest);
board[start] = tile;
System.out.println("Created snake " + "[" + start+ "," + dest + "]");
}
}
public void setLadders(int n) {
//this function generates ladders randomly
for (int i = 0; i < n; i++) {
boolean flag = true;
int start = 0;
int dest = 0;
while (flag) {
start = secureRandom.nextInt(80);
if (!occupiedPositions.contains(start)) {
occupiedPositions.add(start);
break;
}
}
while (flag) {
//this step places the destination for the ladder tile to greater than its position
dest = (int) (start + secureRandom.nextDouble() * 10);
if (!occupiedPositions.contains(dest)) {
occupiedPositions.add(dest);
break;
}
}
Tile tile = new TileImpl(TileType.LADDER, dest);
board[start] = tile;
System.out.println("Created ladder " + "[" + start+ "," + dest + "]");
}
}
}
Lớp PlayerImpl:
public class PlayerImpl implements Player{
private int position = 0;
private String name = null;
public PlayerImpl(String name){
this.name = name;
}
@Override
public int getPosition() {
return position;
}
@Override
public String getName() {
return name;
}
@Override
public void setPosition(int currentPosition) {
this.position = currentPosition;
}
@Override
public void setName(String playerName) {
this.name = playerName;
}
}
Lớp TileImpl:
public class TileImpl implements Tile {
private TileType type;
private int position;
private int destination;
public TileImpl(TileType type) {
this.type = type;
}
public TileImpl(TileType type, int dest) {
this.type = type;
this.destination = dest;
}
public int getPosition() {
return position;
}
public int getDestination() {
return destination;
}
public void setType(TileType type) {
this.type = type;
}
public void setPosition(int position) {
this.position = position;
}
public void setDestination(int destination) {
this.destination = destination;
}
@Override
public TileType getType() {
return type;
}
}
Lớp SnakesAndLadders:
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class SnakesAndLadders {
public static void main(String args[]){
Board board = new BoardImpl();
List<Player> players = new ArrayList<>();
System.out.println("How many players ?");
Scanner scan = new Scanner(System.in);
int noOfPlayers = scan.nextInt();
for(int i = 0; i < noOfPlayers; i++){
System.out.println("Enter name for player "+ i);
String name = scan.next();
Player player = new PlayerImpl(name);
players.add(player);
}
board.initialize();
int counter = 0;
System.out.println("Lets Play!");
String choice = "";
SecureRandom random = new SecureRandom();
//simulating a game through the do while loop
do{
if(counter >= noOfPlayers) counter = 0;
Player currPlayer = players.get(counter);
System.out.println(" Player " + currPlayer.getName() + " turn to play!");
System.out.println(" R = Roll the dice, Q = quit");
choice = scan.next();
if(choice.equalsIgnoreCase("R")){
int places = random.nextInt(6) + 1;
board.movePlayer(currPlayer, places);
counter++;
}
}while(!choice.equalsIgnoreCase("Q"));
}
}
Tôi nghĩ trận đấu rất thẳng về phía trước. Tôi muốn đặc biệt biết nếu
Có một cách tốt hơn để tạo ra số lượng rắn và thang ngẫu nhiên.
Cấu trúc dữ liệu tốt hơn và thích hợp hơn để đại diện cho 'hội đồng quản trị'
Nếu mã của tôi có thể được cải thiện để chứa bất kỳ mô hình / thực hành quan trọng nào.
Trả lời
Chào mừng bạn đến với Đánh giá mã. Triển khai tốt và cấu trúc tốt của mã, tìm các đề xuất của tôi theo dòng.
- Có một cách tốt hơn để tạo ra số lượng rắn và thang ngẫu nhiên.
Các phương pháp setSnakesvà chỉ setLadderskhác nhau một vài dòng mã, đó là một dấu hiệu của sự trùng lặp mã. Đây là phương pháp setLadders:
public void setLadders(int n) {
//this function generates ladders randomly
for (int i = 0; i < n; i++) {
boolean flag = true;
int start = 0;
int dest = 0;
while (flag) {
start = secureRandom.nextInt(80);
if (!occupiedPositions.contains(start)) {
occupiedPositions.add(start);
break;
}
}
while (flag) {
//this step places the destination for the ladder tile to greater than its position
dest = (int) (start + secureRandom.nextDouble() * 10);
if (!occupiedPositions.contains(dest)) {
occupiedPositions.add(dest);
break;
}
}
Tile tile = new TileImpl(TileType.LADDER, dest);
board[start] = tile;
System.out.println("Created ladder " + "[" + start+ "," + dest + "]");
}
}
Một cách tiếp cận là tạo ra một phương pháp để tạo ra các số ngẫu nhiên và sau đó sử dụng nó để tạo thang và rắn. Ví dụ:
private void setRandomLadder() {
while (true) {
int[] segment = getRandomSegment(1,99);
int start = segment[0];
int end = segment[1];
if (isTileFree(start) && isTileFree(end)) {
board[start] = new TileImpl(TileType.LADDER, end);
board[end] = new TileImpl(TileType.OCCUPIED);
break;
}
}
}
Phương pháp này có thể được gọi nlần tùy thuộc vào số bậc thang bạn muốn thêm vào bảng. Phương thức getRandomSegmenttrả về hai điểm ngẫu nhiên từ 1 đến 99. Ngoài ra, tôi đã thay đổi tên từ setLaddersthành setRandomLadder, để làm cho nó tự mô tả. Cuối cùng, hãy nhớ rằng nếu bạn thêm quá nhiều thang, các phương pháp như vậy sẽ không bao giờ hoàn thành, vì vậy hãy xem xét để kiểm tra xem có ô trống trước đó không.
- Cấu trúc dữ liệu tốt hơn và thích hợp hơn để đại diện cho 'hội đồng quản trị'
Bằng cách sử dụng phương pháp trước, chúng tôi có thể xóa danh sách occupiedPositions, điều này có thể thực hiện được bằng cách thêm TileType.OCCUPIED.
Mảng của Tilelà cấu trúc dữ liệu ok, một giải pháp thay thế là sử dụng ArrayList.
- Nếu mã của tôi có thể được cải thiện để chứa bất kỳ mô hình / thực hành quan trọng nào.
Đầu ra bảng điều khiển :
How many players ? 2 Enter name for player 0Thật khó hiểu cho người dùng khi thấy trình phát 0, bắt đầu từ trình phát 1.
Magic số :
new Tile[101],secureRandom.nextInt(98), vv Tạo hằng, ví dụ:private static final int SIZE = 101;Modifier : các phương thức
setSnakesvàsetLaddersphải là private, giống nhau cho tất cả các biến phiên bản.Khởi tạo trong hàm tạo :
BoardImplcó một phương thứcinitialize()nhưng và hàm tạo rỗng. Bạn có thể sử dụng trực tiếp hàm tạo.Encapsulation : giao diện
Boardchấp nhận aPlayervới publicsetPosition, có nghĩa là bất kỳ ai cũng có thể thay đổi nó. Chỉ có hội đồng quản trị nên thay đổi trạng thái của người chơi. Một giao diện an toàn hơn có thể là:public interface Board { void movePlayer(String playerId, int places); //.. }Tránh các biến tạm thời : thay vì
Tile tile = new TileImpl(TileType.LADDER, dest); board[start] = tile;Bạn có thể viết:
board[start] = new TileImpl(TileType.LADDER, dest);Mùi mã :
public String checkEndingPosition(int currentPosition, int places){ if((currentPosition + places) > 100){ return "outOfBoard"; }else if((currentPosition+ places) == 100){ return "winner"; } else{ return "valid"; } }Trả về một chuỗi rất dễ xảy ra lỗi ở đây. Ví dụ, bạn có thể trả về một boolean và cuối cùng là một ngoại lệ.
Kiểm tra và khả năng sử dụng lại : phương thức
winnergọiSystem.exit(0), khiến nó không thể kiểm tra. Ngoài ra, có rất nhiềuSystem.out.printlntrongBoardImpllớp. Rất khó để kiểm tra một lớp học như vậy. Tốt nhất, lớpBoardkhông bao giờ được in cho người dùng, chỉ để gỡ lỗi. Cácmainphải có trách nhiệm để tương tác với người dùng.
Khả năng đọc và phong cách
Vui lòng chạy mã của bạn thông qua trình định dạng để làm cho mã dễ đọc hơn và tuân theo các tiêu chuẩn.
Cái này có thể hoạt động:
https://www.tutorialspoint.com/online_java_formatter.htm
Cờ?
boolean flag = true;
int start = 0;
int dest = 0;
while (flag) {
start = secureRandom.nextInt(80);
if (!occupiedPositions.contains(start)) {
occupiedPositions.add(start);
break;
}
}
Bạn đang không sử dụng, hãy kiểm tra hoặc thay đổi cờ ở đây. Vòng lặp này chỉ nên như vậy while(true)và vòng lặp tiếp theo cũng làm điều tương tự.
Nếu khác-
if(checkPos.equals("winner")){
winner(player);
}
Khi bạn đang kiểm tra một số trường hợp độc quyền và so sánh với một chuỗi, tôi nghĩ rằng một switchcâu lệnh là cách thích hợp / tiêu chuẩn hơn để làm điều đó. Nó cũng làm rõ ràng hơn rằng các trường hợp là độc quyền.
Cấu trúc dữ liệu
Set<Integer> occupiedPositions = new HashSet<>();
Điều này có vẻ không cần thiết / không tự nhiên đối với tôi. Tôi sẽ thêm vào lớp Tile a boolđể đánh dấu một ô là bị chiếm dụng, và sau đó thông tin đó có thể được chứa trong chính ô / bảng thay vì có một ô riêng biệt Setđể ghi sổ.