@@ -1,43 +1,112 @@
|
|||||||
package it.polimi.ingsw.gc14.View.TUI;
|
package it.polimi.ingsw.gc14.View.TUI;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
// Helper generale per costruire tabelle ASCII
|
* General-purpose helper for building fixed-width ASCII/Unicode tables in a TUI.
|
||||||
|
*
|
||||||
|
* <p>A table is built by adding rows one at a time, then calling {@link #build()}
|
||||||
|
* to obtain the fully rendered string. Column width is computed automatically
|
||||||
|
* from the widest cell across all rows.
|
||||||
|
*
|
||||||
|
* <p>Example usage:
|
||||||
|
* <pre>{@code
|
||||||
|
* AsciiTable table = new AsciiTable(BorderStyle.UNICODE, 3);
|
||||||
|
* table.addHeader("Name", "Food", "PP");
|
||||||
|
* table.addRow("Alice", "4", "12");
|
||||||
|
* table.addRow("Bob", "2", "8");
|
||||||
|
* System.out.println(table.build());
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
public class AsciiTable {
|
public class AsciiTable {
|
||||||
//TODO javadoc
|
|
||||||
|
/**
|
||||||
|
* The border style used to draw the table (e.g. Unicode box-drawing,
|
||||||
|
* plain ASCII, rounded corners).
|
||||||
|
*/
|
||||||
private final BorderStyle s;
|
private final BorderStyle s;
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* The number of columns in the table.
|
||||||
|
* Every row added via {@link #addRow} must contain exactly this many cells.
|
||||||
|
*/
|
||||||
private final int cols;
|
private final int cols;
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* The rows of the table, each represented as a list of cell strings.
|
||||||
|
* Rows are stored in display order; {@link #addHeader} inserts at index 0.
|
||||||
|
*/
|
||||||
private final List<List<String>> rows = new ArrayList<>();
|
private final List<List<String>> rows = new ArrayList<>();
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Row indices after which a horizontal separator line is drawn.
|
||||||
|
* Populated by {@link #addHeader} and {@link #addSeparator}.
|
||||||
|
*/
|
||||||
private final List<Integer> separators = new ArrayList<>();
|
private final List<Integer> separators = new ArrayList<>();
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Constructs an empty {@code AsciiTable} with the given border style
|
||||||
|
* and column count.
|
||||||
|
*
|
||||||
|
* @param s the {@link BorderStyle} to use for box-drawing characters
|
||||||
|
* @param cols the number of columns; every row must supply exactly this
|
||||||
|
* many cells
|
||||||
|
*/
|
||||||
public AsciiTable(BorderStyle s, int cols) {
|
public AsciiTable(BorderStyle s, int cols) {
|
||||||
this.s = s; this.cols = cols;
|
this.s = s; this.cols = cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Appends a row at the bottom of the table.
|
||||||
|
*
|
||||||
|
* @param cells one string per column, in left-to-right order
|
||||||
|
*/
|
||||||
public void addRow(String... cells) { rows.add(Arrays.asList(cells)); }
|
public void addRow(String... cells) { rows.add(Arrays.asList(cells)); }
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Appends a row at the bottom of the table.
|
||||||
|
*
|
||||||
|
* @param cells a list of strings, one per column, in left-to-right order
|
||||||
|
*/
|
||||||
public void addRow(List<String> cells) { rows.add(cells); }
|
public void addRow(List<String> cells) { rows.add(cells); }
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
public void addHeader(String... cells) { rows.add(0, Arrays.asList(cells)); separators.add(0); }
|
* Inserts a header row at the top of the table and marks it with a
|
||||||
|
* horizontal separator so that a dividing line is drawn below it.
|
||||||
|
*
|
||||||
|
* <p>Calling this method after rows have already been added will push
|
||||||
|
* all existing rows down by one position.
|
||||||
|
*
|
||||||
|
* @param cells one string per column, in left-to-right order
|
||||||
|
*/
|
||||||
|
public void addHeader(String... cells) {
|
||||||
|
rows.add(0, Arrays.asList(cells));
|
||||||
|
separators.add(0);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
public void addSeparator() { separators.add(rows.size()-1); }
|
* Marks the current last row so that a horizontal separator line is
|
||||||
|
* drawn below it when the table is built.
|
||||||
|
*
|
||||||
|
* <p>Call this method immediately after the row that should be followed
|
||||||
|
* by the separator.
|
||||||
|
*/
|
||||||
|
public void addSeparator() { separators.add(rows.size() - 1); }
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Renders the table to a multi-line string.
|
||||||
|
*
|
||||||
|
* <p>Column width is determined dynamically as the length of the longest
|
||||||
|
* cell across all rows, plus one padding space. All cells are left-aligned
|
||||||
|
* and padded or truncated to the same width.
|
||||||
|
*
|
||||||
|
* @return the fully rendered table as a single string with embedded newlines
|
||||||
|
*/
|
||||||
public String build() {
|
public String build() {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
int maxWidth = rows.stream().mapToInt(x->x.stream().mapToInt(y->y.length()).max().getAsInt()).max().getAsInt()+1;
|
int maxWidth = rows.stream()
|
||||||
sb.append(hline(s.tl(), s.mt(), s.tr(),maxWidth)).append('\n');
|
.mapToInt(x -> x.stream().mapToInt(y -> y.length()).max().getAsInt())
|
||||||
|
.max().getAsInt() + 1;
|
||||||
|
sb.append(hline(s.tl(), s.mt(), s.tr(), maxWidth)).append('\n');
|
||||||
|
|
||||||
for (int i = 0; i < rows.size(); i++) {
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
sb.append(s.v());
|
sb.append(s.v());
|
||||||
@@ -45,14 +114,23 @@ public class AsciiTable {
|
|||||||
sb.append(rpad(" " + cell, maxWidth)).append(s.v());
|
sb.append(rpad(" " + cell, maxWidth)).append(s.v());
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
if (separators.contains(i) && i < rows.size() - 1)
|
if (separators.contains(i) && i < rows.size() - 1)
|
||||||
sb.append(hline(s.sl(), s.sx(), s.sr(),maxWidth)).append('\n');
|
sb.append(hline(s.sl(), s.sx(), s.sr(), maxWidth)).append('\n');
|
||||||
}
|
}
|
||||||
sb.append(hline(s.bl(), s.mb(), s.br(), maxWidth));
|
sb.append(hline(s.bl(), s.mb(), s.br(), maxWidth));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
private String hline(String l, String m, String r,int maxWidth) {
|
* Builds a single horizontal border line spanning all columns.
|
||||||
|
*
|
||||||
|
* @param l the left-end character (e.g. {@code ╔}, {@code ╠}, {@code ╚})
|
||||||
|
* @param m the column-junction character (e.g. {@code ╦}, {@code ╬}, {@code ╩})
|
||||||
|
* @param r the right-end character (e.g. {@code ╗}, {@code ╣}, {@code ╝})
|
||||||
|
* @param maxWidth the width in characters of each column segment,
|
||||||
|
* filled with the horizontal line character of the current style
|
||||||
|
* @return the rendered horizontal line as a string
|
||||||
|
*/
|
||||||
|
private String hline(String l, String m, String r, int maxWidth) {
|
||||||
var sb = new StringBuilder(l);
|
var sb = new StringBuilder(l);
|
||||||
for (int i = 0; i < cols; i++) {
|
for (int i = 0; i < cols; i++) {
|
||||||
sb.append(s.h().repeat(maxWidth));
|
sb.append(s.h().repeat(maxWidth));
|
||||||
@@ -61,13 +139,40 @@ public class AsciiTable {
|
|||||||
return sb.append(r).toString();
|
return sb.append(r).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Right-pads a string with spaces to the given width, or truncates it
|
||||||
|
* if it exceeds that width.
|
||||||
|
*
|
||||||
|
* @param s the input string
|
||||||
|
* @param w the desired output width in characters
|
||||||
|
* @return a string of exactly {@code w} characters
|
||||||
|
*/
|
||||||
private static String rpad(String s, int w) {
|
private static String rpad(String s, int w) {
|
||||||
if (s.length() >= w) return s.substring(0, w);
|
if (s.length() >= w) return s.substring(0, w);
|
||||||
return s + " ".repeat(w - s.length());
|
return s + " ".repeat(w - s.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO javadoc
|
/**
|
||||||
|
* Places two pre-rendered text blocks side by side, separated by a gap.
|
||||||
|
*
|
||||||
|
* <p>Each block is a list of lines as returned by {@link #build()}.
|
||||||
|
* Lines in the left block are padded to a uniform width so that the
|
||||||
|
* right block always starts at the same horizontal position. If one
|
||||||
|
* block is taller than the other, the shorter one is padded with blank
|
||||||
|
* lines.
|
||||||
|
*
|
||||||
|
* <p>Example:
|
||||||
|
* <pre>{@code
|
||||||
|
* List<String> left = Arrays.asList(table1.build().split("\n"));
|
||||||
|
* List<String> right = Arrays.asList(table2.build().split("\n"));
|
||||||
|
* System.out.print(AsciiTable.sideBySide(left, right, 2));
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param left lines of the left block
|
||||||
|
* @param right lines of the right block
|
||||||
|
* @param gap number of blank spaces between the two blocks
|
||||||
|
* @return the merged string with embedded newlines
|
||||||
|
*/
|
||||||
public static String sideBySide(List<String> left, List<String> right, int gap) {
|
public static String sideBySide(List<String> left, List<String> right, int gap) {
|
||||||
int leftWidth = left.stream().mapToInt(String::length).max().orElse(0);
|
int leftWidth = left.stream().mapToInt(String::length).max().orElse(0);
|
||||||
int maxHeight = Math.max(left.size(), right.size());
|
int maxHeight = Math.max(left.size(), right.size());
|
||||||
@@ -75,17 +180,11 @@ public class AsciiTable {
|
|||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
for (int i = 0; i < maxHeight; i++) {
|
for (int i = 0; i < maxHeight; i++) {
|
||||||
String l = i < left.size()
|
String l = i < left.size() ? left.get(i) : " ".repeat(leftWidth);
|
||||||
? left.get(i)
|
|
||||||
: " ".repeat(leftWidth);
|
|
||||||
|
|
||||||
// padda la riga sinistra se è più corta delle altre
|
|
||||||
l = rpad(l, leftWidth);
|
l = rpad(l, leftWidth);
|
||||||
|
|
||||||
String r = i < right.size() ? right.get(i) : "";
|
String r = i < right.size() ? right.get(i) : "";
|
||||||
sb.append(l).append(padding).append(r).append('\n');
|
sb.append(l).append(padding).append(r).append('\n');
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,113 +4,214 @@ import it.polimi.ingsw.gc14.View.IView;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text-based User Interface (TUI) implementation of {@link IView}.
|
||||||
|
*
|
||||||
|
* <p>Renders the current state of a {@link Game} model directly to the
|
||||||
|
* standard output using Unicode box-drawing characters and fixed-width
|
||||||
|
* ASCII tables (see {@link AsciiTable}).
|
||||||
|
*
|
||||||
|
* <p>The display is split into two side-by-side panels:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>Left panel</b> — board or player status, depending on the render method called.</li>
|
||||||
|
* <li><b>Right panel</b> — menu options legend and the current player's hand.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>The terminal is cleared before each render via a platform-aware
|
||||||
|
* {@code cls} / {@code clear} system call.
|
||||||
|
*
|
||||||
|
* <p>Typical usage:
|
||||||
|
* <pre>{@code
|
||||||
|
* TUI tui = new TUI(game);
|
||||||
|
* tui.setUsername("Alice");
|
||||||
|
* tui.fullRender();
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
public class TUI implements IView {
|
public class TUI implements IView {
|
||||||
|
|
||||||
// ── dati di stato ───────────────────────────────────────────
|
/**
|
||||||
private BorderStyle style = BorderStyle.UNICODE;
|
* The {@link Game} model whose state is rendered.
|
||||||
|
* Updated via {@link #update(Game)} whenever the game state changes.
|
||||||
|
*/
|
||||||
private Game model;
|
private Game model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username of the local player, used to retrieve and display
|
||||||
|
* that player's hand in the right panel.
|
||||||
|
*
|
||||||
|
* @see #setUsername(String)
|
||||||
|
*/
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@code TUI} bound to the given game model.
|
||||||
|
* The username is initialised to an empty string and must be set
|
||||||
|
* separately via {@link #setUsername(String)} before calling any
|
||||||
|
* render method that displays the player's hand.
|
||||||
|
*
|
||||||
|
* @param model the {@link Game} model to display; must not be {@code null}
|
||||||
|
*/
|
||||||
public TUI(Game model) {
|
public TUI(Game model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.username="";
|
this.username = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the username of the local player.
|
||||||
|
* This value is used by {@link #renderBoard()} and {@link #fullRender()}
|
||||||
|
* to look up the correct player hand via
|
||||||
|
* {@link Game#getPlayerByUsername(String)}.
|
||||||
|
*
|
||||||
|
* @param username the player's username; must match an existing player
|
||||||
|
* in the current {@link Game} model
|
||||||
|
*/
|
||||||
public void setUsername(String username) {
|
public void setUsername(String username) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the game model stored in this view.
|
||||||
|
* Should be called whenever the game state changes so that the next
|
||||||
|
* render reflects the latest state.
|
||||||
|
*
|
||||||
|
* @param model the new {@link Game} model; must not be {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(Game model) {
|
public void update(Game model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── punto di ingresso ───────────────────────────────────────
|
/**
|
||||||
public void render()
|
* Default render entry point, as required by {@link IView}.
|
||||||
{
|
* Delegates to {@link #renderBoard()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
renderBoard();
|
renderBoard();
|
||||||
}
|
}
|
||||||
public void fullRender()
|
|
||||||
{
|
|
||||||
try{
|
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
|
||||||
ProcessBuilder pb;
|
|
||||||
if (os.contains("win")) {
|
|
||||||
pb = new ProcessBuilder("cmd", "/c", "cls");
|
|
||||||
} else {
|
|
||||||
pb = new ProcessBuilder("clear");
|
|
||||||
}
|
|
||||||
pb.inheritIO().start().waitFor();
|
|
||||||
}
|
|
||||||
catch(Exception e){
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String>lines=List.of(model.BoardStamp().split("\n"));
|
/**
|
||||||
List<String> lines2=List.of((PrintMenuOptions()+"\n"+model.getPlayerByUsername(username)).split("\n"));
|
* Renders a full view of the game, combining both player status
|
||||||
System.out.println(model.PlayersStamp()+"\n"+ AsciiTable.sideBySide(lines,lines2,3));
|
* and board status.
|
||||||
|
*
|
||||||
|
* <p>Layout:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>Top</b> — player status table produced by
|
||||||
|
* {@link Game#PlayersStamp()}.</li>
|
||||||
|
* <li><b>Bottom-left</b> — board status produced by
|
||||||
|
* {@link Game#BoardStamp()}.</li>
|
||||||
|
* <li><b>Bottom-right</b> — menu options legend and the local
|
||||||
|
* player's hand.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>The terminal is cleared before rendering.
|
||||||
|
*/
|
||||||
|
public void fullRender() {
|
||||||
|
clearTerminal();
|
||||||
|
List<String> lines = List.of(model.BoardStamp().split("\n"));
|
||||||
|
List<String> lines2 = List.of((printMenuOptions() + "\n" +
|
||||||
|
model.getPlayerByUsername(username)).split("\n"));
|
||||||
|
System.out.println(model.PlayersStamp() + "\n" +
|
||||||
|
AsciiTable.sideBySide(lines, lines2, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderBoard()
|
/**
|
||||||
{
|
* Renders the board status only.
|
||||||
try{
|
*
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
* <p>Layout:
|
||||||
ProcessBuilder pb;
|
* <ul>
|
||||||
if (os.contains("win")) {
|
* <li><b>Left panel</b> — turn order, upper card row, offer track,
|
||||||
pb = new ProcessBuilder("cmd", "/c", "cls");
|
* and lower card row, as produced by {@link Game#BoardStamp()}.</li>
|
||||||
} else {
|
* <li><b>Right panel</b> — menu options legend followed by the local
|
||||||
pb = new ProcessBuilder("clear");
|
* player's hand.</li>
|
||||||
}
|
* </ul>
|
||||||
pb.inheritIO().start().waitFor();
|
*
|
||||||
}
|
* <p>The terminal is cleared before rendering.
|
||||||
catch(Exception e){
|
*/
|
||||||
}
|
public void renderBoard() {
|
||||||
List<String>lines=List.of(model.BoardStamp().split("\n"));
|
clearTerminal();
|
||||||
List<String> lines2=List.of((PrintMenuOptions()+"\nYOUR HAND\n"+model.getPlayerByUsername(username)).split("\n"));
|
List<String> lines = List.of(model.BoardStamp().split("\n"));
|
||||||
System.out.println(AsciiTable.sideBySide(lines,lines2,3));
|
List<String> lines2 = List.of((printMenuOptions() + "\nYOUR HAND\n" +
|
||||||
}
|
model.getPlayerByUsername(username)).split("\n"));
|
||||||
public void renderPlayer()
|
System.out.println(AsciiTable.sideBySide(lines, lines2, 3));
|
||||||
{
|
|
||||||
try{
|
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
|
||||||
ProcessBuilder pb;
|
|
||||||
if (os.contains("win")) {
|
|
||||||
pb = new ProcessBuilder("cmd", "/c", "cls");
|
|
||||||
} else {
|
|
||||||
pb = new ProcessBuilder("clear");
|
|
||||||
}
|
|
||||||
pb.inheritIO().start().waitFor();
|
|
||||||
}
|
|
||||||
catch(Exception e){
|
|
||||||
}
|
|
||||||
List<String>lines=List.of(model.PlayersStamp().split("\n"));
|
|
||||||
List<String> lines2=List.of(PrintMenuOptions().split("\n"));
|
|
||||||
System.out.println(AsciiTable.sideBySide(lines,lines2,3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showMessage(String message)
|
/**
|
||||||
{
|
* Renders the player status table only.
|
||||||
|
*
|
||||||
|
* <p>Layout:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>Left panel</b> — prestige, food, character deck, and building
|
||||||
|
* deck for all players, as produced by {@link Game#PlayersStamp()}.</li>
|
||||||
|
* <li><b>Right panel</b> — menu options legend.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>The terminal is cleared before rendering.
|
||||||
|
*/
|
||||||
|
public void renderPlayer() {
|
||||||
|
clearTerminal();
|
||||||
|
List<String> lines = List.of(model.PlayersStamp().split("\n"));
|
||||||
|
List<String> lines2 = List.of(printMenuOptions().split("\n"));
|
||||||
|
System.out.println(AsciiTable.sideBySide(lines, lines2, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a plain message to standard output.
|
||||||
|
*
|
||||||
|
* @param message the message to display
|
||||||
|
*/
|
||||||
|
public void showMessage(String message) {
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public void showError(String message)
|
* Prints an error message to standard output.
|
||||||
{
|
*
|
||||||
|
* @param message the error message to display
|
||||||
|
*/
|
||||||
|
public void showError(String message) {
|
||||||
|
clearTerminal();
|
||||||
|
render();
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String PrintMenuOptions()
|
/**
|
||||||
{
|
* Builds and returns the menu options panel as a two-column
|
||||||
var table=new AsciiTable(BorderStyle.ROUNDED,2);
|
* {@link AsciiTable} with rounded borders.
|
||||||
table.addHeader( "Menu Options","Render Options");
|
*
|
||||||
table.addRow( List.of("0-SlotChoice(pos)","A-Full Render"));
|
* <p>The left column lists game action commands (slot choice, draw, pick…),
|
||||||
table.addRow(List.of("1-DrawUpperTribe(pos)","B-Board Render"));
|
* the right column lists render shortcuts (full, board, players).
|
||||||
table.addRow(List.of("2-DrawUpperBuilding(pos)","C-Players Render"));
|
*
|
||||||
table.addRow(List.of("3-DrawLowerTribe(pos)",""));
|
* @return the rendered menu table as a multi-line string
|
||||||
table.addRow(List.of("4-DrawLowerBuilding(pos)",""));
|
*/
|
||||||
table.addRow(List.of("5-PickOptionalTribe(pos)",""));
|
private String printMenuOptions() {
|
||||||
table.addRow(List.of("6-PickOptionalBuilding(pos)",""));
|
var table = new AsciiTable(BorderStyle.ROUNDED, 2);
|
||||||
table.addRow(List.of("7-NoOptional",""));
|
table.addHeader("Menu Options", "Render Options");
|
||||||
table.addRow(List.of("8-NoUpperCard",""));
|
table.addRow(List.of("0-SlotChoice(pos)", "A-Full Render"));
|
||||||
table.addRow(List.of("9-NoLowerCard",""));
|
table.addRow(List.of("1-DrawUpperTribe(pos)", "B-Board Render"));
|
||||||
|
table.addRow(List.of("2-DrawUpperBuilding(pos)", "C-Players Render"));
|
||||||
|
table.addRow(List.of("3-DrawLowerTribe(pos)", ""));
|
||||||
|
table.addRow(List.of("4-DrawLowerBuilding(pos)", ""));
|
||||||
|
table.addRow(List.of("5-PickOptionalTribe(pos)", ""));
|
||||||
|
table.addRow(List.of("6-PickOptionalBuilding(pos)", ""));
|
||||||
|
table.addRow(List.of("7-NoOptional", ""));
|
||||||
|
table.addRow(List.of("8-NoUpperCard", ""));
|
||||||
|
table.addRow(List.of("9-NoLowerCard", ""));
|
||||||
return table.build();
|
return table.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the terminal using a platform-aware system call.
|
||||||
|
* Uses {@code cls} on Windows and {@code clear} on Unix-like systems.
|
||||||
|
* Failures are silently ignored to avoid interrupting the render flow.
|
||||||
|
*/
|
||||||
|
private void clearTerminal() {
|
||||||
|
try {
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
ProcessBuilder pb = os.contains("win")
|
||||||
|
? new ProcessBuilder("cmd", "/c", "cls")
|
||||||
|
: new ProcessBuilder("clear");
|
||||||
|
pb.inheritIO().start().waitFor();
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user