I trying to complete a RPG game for a project, but have no idea on how to make the game map.
It doesn't need to be graphical, but the code for the whole map and each tile must be correct.
So far, I thought about making a non-matricial map (as request by the professor) by using an ArrayList which contain all the linked tiles.
public abstract class Casella {
/**
* #uml.property name="tabellone"
* #uml.associationEnd multiplicity="(1 1)" inverse="casella:Tabellone"
* #uml.association name="contains"
*/
private int id;
private boolean free = true;
private List adjacent;
private List items;
private Tabellone tabellone = null;
public void in(){
free = false;
}
public void out(){
free = true;
}
}
This was the code for a single tile (which has 3 classes that extends it). I still have no idea on how to put together and generate a map.
Thank you for your time.
Don't start with the implementation, start with how you would like to use the map. That will give you some constraints how to implement it. For example:
When drawing the map, how do you access it? By coordinate? Or by "go west from tile X"?
[EDIT] I suggest to start with the main loop of the RPG game. You'll need to place the character/token somewhere (i.e. it needs some kind of relation to a tile).
Then you need to move the character. A character must be able to examine the current tile (opponents, items, type). It needs a way to know how it can move (i.e. is there a wall to the right?)
This gives you an interface for your map: Services which it renders for other objects in the game. When you have an idea of what the interface needs to provide, that should give you an idea how to implement the map (the data structure).
As for generating a map, use a random number generator plus some "common sense". Have a look at the adjacent tiles: When they are all city, this tile is probably city, too. Same for plains. Hills are singular items, and they are least frequent.
Run this code, print the map as ASCII ("C"ity, "P"lain, "H"ill) to see if it works.
To generate a map like this without using a matrix, I recommend starting with a center tile and then populating the map outwards by using a modified breadth first search algorithm. First of all, we'll need something a little better than a list of adjacent tiles. You could simply have four variables, one for each direction that stores the next tile, as such:
private Tabellone up = null;
private Tabellone down = null;
private Tabellone left = null;
private Tabellone right = null;
Say we start with the center-most tile. All you have to do now is figure out how many of the directions are null, and create a new Tablellone object for each direction, making sure to set each of the variables in this current object and to set the appropriate opposite variable in the object created.
Tabellone adj = new Tabellone();
up = adj;
adj.setDown(this);
Once you've filled out all of the directions on this tile, you then choose one of the other tiles you've created and perform the same operation. This is where the breadth-first search algorithm comes in. You can use a queue to go through each tile you've created and fill out the directions. To make the algorithm stop, simply set a limit on the number of tiles you want to create and use a counter to keep track of how many have been created.
int count = 0;
ArrayList<Tabellone> queue = new ArrayList<Tabellone>()
queue.add(/*center tile*/);
while (count < 100) { //if we want 100 tiles
//take out the center tile from the beginning of the array list, create a tile for each direction and add those tiles to the array list, then increment count by 1.
}
Note: This algorithm as it stands will create a diamond shaped map, if you want a square, you'd need to have a variable for each diagonal direction as well.
Of course, if this seems a little more complicated than you'd like, I'd recommend a coordinate system.
The walls, baggs and areas are special containers, which will hold all the walls, baggs and areas of the game.
private String level =
" ######\n"
+ " ## #\n"
+ " ##$ #\n"
+ " #### $##\n"
+ " ## $ $ #\n"
+ "#### # ## # ######\n"
+ "## # ## ##### ..#\n"
+ "## $ $ ..#\n"
+ "###### ### #### ..#\n"
+ " ## #########\n"
+ " ########\n";
This is the level of the game. Except for the space, there are five characters. The hash (#) stands for a wall. The dollar ($) represents the box to move. The dot (.) character represents the place where we must move the box. The at character (#) is the sokoban. And finally the new line character (\n) starts a new row of the world.
Is speed or memory a huge concern for this project? If not, why don't you use a 2d array?
Something like
Casella map [][] = new Casella[xSize][ySize];
From here it is easy to conceptualize, just picture it as an excel spreadsheet where each cell is a tile on the map.
The way you are going is fine though, just a little hard to conceptualize sometimes. You have a List of adjacent tiles. So, when creating your map you start somewhere, possibly top left, and go from there.
You could use nested for loops in order to set up the map, and to help determine the edge items.
for(int i = 0; i < XSIZE ; ++i)
for(int j = 0; j < YSIZE ; ++j)
if(j==0) //found left edge (i.e. no adjacent ones to the left)
if(j==(YSIZE)) //found right edge (you get the picture)
The point of using the loops, and checking the edges, is that you are going to need to link backwards and forward, up and down for each tile except at the edges, where you will have either 2 or 3 links instead of 4.
The code needs to be correct really isn't a functional requirement, so its hard to say exactly what is correct without knowing more about your game/map.
Assuming you have a map that has X tiles and no ordered adjacency a non-matricial solution is best, a common solution is to just model it like a graph using either adjacency list for non-symmetric adjacency or incidence list for symmetric adjacency. If youre using an incidence list you need an edge object that contain the vertices the edge is connecting, if youre using adjacency list a multimap might be cool to use.
If you want a non-matricial solution with ordered adjacency AlbertoPL has the solution for that.
Assuming you have a map thats X tiles wide and Y tiles tall and the tiles that are next to each other are adjacent, so that each tile has at max 4 and min 2 adjacent tiles you could use a matrix to access the tiles and also represent adjacency by matricial adjacency. The idea is that map[Y][X] is adjacent to map[Y+1][X] and map[Y][X+1] and reversely.
This solution could also fit max 6 and min 3 tile adjacency if tile [Y+1][X+1] is adjacent to tile [Y][X].
Upside to this is that you can easily parse the map, and since it has 2 dimensions its natural to model it like this.
Downside is that once a tile is set, you cant change its adjacency without changing the matrix. As this isnt what you professor suggested you might not want to do it, but if you have (static) ordered adjacency this might be easiest way to do it.
I managed this by using adjacency lists.
Each cell will have an ArrayList containing the indexes of the adjacent cells. Those indexes are the ones that the said cell have in the map ArrayList of cells.
http://en.wikipedia.org/wiki/Adjacency_list
If it's a tile-based map, then each room has a fixed relationship with its adjacent rooms. You may not need to worry about co-ordinates (although it might be simpler if the tiles are square), but you will need to worry about directions.
If the tiles are square, cardinal directions (n, s, e, w) may be all you need care about. If they're hex tiles, you can number your exits 1-6 (perhaps with static final constants). Then each adjacent tile may be linked to this one along with its exit.
As said by Aaron, you need to decide first how the maping coordinates will be.
But you are not constrained by an X-Y-Z coordinate system. For instance, each tile could be linked to any other tile on your map. It all depends on how you want to build it.
You say that you're building an RPG game, then you need to have a good view of the terrain surround your character. Is it multi-level? How does the character move from one tile to another? Is the movement one way?
There are, literally, dozens of question to be asked when designing a map for a game.
You need to plan it very well first, before starting coding.
Related
I'm writing a chess engine in Java and using bitboards to represent the board (12 64-bit numbers). The size of an instance of this class(its retained size) is 152Bytes according to IntelliJ debugger.
When trying to see a few moves a head, for each move I consider I create a new instance to represent the new Board state. Below is what the Board class looks like approximately.
public long WP=0L, WN=0L, WB=0L, WR=0L, WQ=0L, WK=0L, BP=0L, BN=0L, BB=0L, BR=0L, BQ=0L, BK=0L;
long NOT_WHITE_PIECES;
long WHITE_PIECES;
long BLACK_PIECES;
long OCCUPIED;
long EMPTY;
public void updateBitboards() {}
public void updateMailbox() {}
public void movePiece(Move move) {}
public void drawBitboard() {}
Other fields and methods are static so I don't think they affect the size of an instance.
The problem is, even if I want to consider only the first 4 moves in chess, there's ~8,000,000 possible combination of moves. So I'm going to end up storing a total of 8,000,000*152B = 1,216,000,000B... which is 1.2GB.
I feel like I'm missing something here. How can I increase the number of positions I consider at a time?
First, you don't want to create a new instance of the board state each move. If you are using e.g. Minimax then you make the move, make recursive call, then unmake the move. This way you always just have one board state which it considers.
Then to minimize the number of moves you need to consider you want to make enhancements to the algorithm. The most common to start with is alpha-beta pruning which you can read more about here: https://www.chessprogramming.org/Alpha-Beta. Alpha beta pruning will always yield the same result as a minimax, but you consider less positions since you don't search the hopeless ones.
Then there are tons of other pruning techniques that you can do to reduce the search tree. Most of these will not yield the same result since you "manually" choose to cut off certain positions that you "think" is going to be bad. This could be things like the assumption that there is always better to do something than nothing (null move pruning).
Other easy things you can do to speed up algorithm is to look at move ordering. To make Minimax most efficient you always want to look at the best move first in each position. That way you will get more cutoffs and not search as many moves. Everything you need to know about chess programming you can find at https://www.chessprogramming.org/.
I'm still trying to improve on my coding skills, and this question has got me spinning in my tracks a little bit, so any help is greatly appreciated. I know how to create the random array very easily, no problem with that. However, the logic of finding the chain is proving very difficult for me. I believe the proper approach is some sort of depth first searching algorithm, but I'm not entirely sure of how to implement that in this scenario, or whether that is even correct.
My basic question is, should I be using depth first search, and if so, should I be doing it recursively? Any tips or hints on implementation are also welcome!
Make a program that creates a 3x3 grid of random
positive numbers where 0 <= n <= 9. The program should
find all possible combinations of numbers that add up to the area of
the grid, or 9, using these rules (similar to Boggle):
a. The numbers must be "chained" in sequentially adjacent cells, where
"adjacent" cells are those horizontally, vertically, and diagonally
neighboring
b. The chain does not have to be in a line. For example, it could go
horizontally once, then vertically once, and finally diagonally once
c. At least the “grid width - 1” cells must be used in the chain (a
3x3 grid means that at least two cells must be used)
d. A chain cannot repeat a grid cell that it has already used
e. Chains that use the exact same cells as a previous chain are
considered repeats and should not be counted
I know that for each element, when you are searching through each adjacent element, you must check and keep track of whether it's been visited before, so you don't repeat numbers.
public class GridSolver {
int[][] workingGrid;
public GridSolver(int[][] workingGrid){
this.workingGrid = workingGrid;
}
public String solve(){
int length = this.workingGrid.length;
boolean[][] visited = new boolean[length][length];
for(int rows=0; rows<length; rows++){
for(int columns=0; columns<length; columns++){
if(visited[rows][columns] == false){
dfs(workingGrid[rows][columns]);
}
}
}
return null;
}
public HashSet<ArrayList<Integer>> dfs(int element){
HashSet<ArrayList<Integer>> chains = new HashSet<>();
checkLeft();
checkTopLeft();
checkTopMiddle();
checkTopRight();
checkRight();
checkBottomRight();
checkBottomMiddle();
checkBottomLeft();
return null;
}}
This is what I have so far and I realize that it is pretty sloppy and not the best thought out scheme, but that's why I'm here I guess :P.
Also just to explain some of my thinking in the code, the dfs()method has a return type of HashSet because I know that you can't have duplicate chains, and it is a set of a list of the chains. Also the "check" methods are not implemented, I just wrote them down because I know that you will need to process each of these adjacent blocks for each number.
Once again, any help is greatly appreciated, and thank you for humoring me as a beginner here!
I'm writing a simple program and want to know if an approximate position is clicked. I've got a hashmap with the position as key value and want to display a currently invisible object if the user clicks close enough to the position of the object - not just right at it. The position class just holds an x and a y value.
HashMap<Position, Place> places = new HashMap<>(); //Assume this is populated
#Override
class WhatIsHere extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
Place place = places.get(new Position(me.getX(), me.getY()));
if (place != null) {
place.setVisible(true);
} else {
System.out.println("Nothing there");
}
}
}
This bit of code finds the place if you click right on it though I don't know how to look for, say, me.getX()+-10 and find objects in that range.
Do I need to set four ints holding x-10 and x+10 etc. and just loop through all the positions inbetween? It seems awfully dumb to do it that way.
I dislike exercises that require use of a particular collection, regardless of whether it is the best choice. One of the most important things to learn about the collections, and more generally about data structures, is picking which to use for a given job.
However, I understand you have to use HashMap. Here is one way to do it.
Divide the space up into small squares. Identify each square by e.g. the Point at the minimum x and minimum y. Create a HashMap that maps the square that are near at least one of your objects to the list of nearby objects.
To look up a point, calculate the Point identifying the square containing it. Look up that Point in the map. If it is not present, your point is not near any object. If it is present, check your point against each object in the list according to your nearness rules.
For some configurations of your objects, you may be able to ensure that each square is near at most one object. If so, you can replace the list with the object.
You might want to use TreeMap and you would be able to get a sub map which seems to be what you are looking for.
I answered that I will have have a 2d Array.
And then I will have 3 functions
one to check the horizontal condition.
another function to check vertical condition
and another one the check the 3*3 block condition.
But he is not satisfied, can any one give a good answer for this question?
I found this stack overflow link related to my question.
Programming Design Help - How to Structure a Sudoku Solver program?.
But I want a proper object oriented design (like what should be the classes, inheritance and other details) which are the same things interviewer expected from me.
To me, your design starts with a "region" class. You can then extend this to be a "horizontal region" "vertical region" and "square region" as the three types of regions. Edit: upon further consideration you don't really need to make this distinction unless it's for display purposes... algorithmically it will be the same.
Then you can make your 2d array of "elements" and add the elements appropriately to your regions, which provides a network for your calculations. Your elements have a list of potential values, and your regions are responsible for removing those potential values. When you have a value found, it triggers the regions it is a member of to remove the potential values from those too.
For base classes of a solver, I see a good start with Cell, ValidationRegion, Board, and Pattern as your main classes.
Cell: Has the current value of the cell, the remaining possible values of the cell, and if the cell is fixed or not.
ValidationRegion: Has references to the appropriate 9 Cells on the Board. This class doesn't really need to know if it is representing horizontal, vertical, or a square regions, because the rules are the same. This class has a validate() method to verify that the current state of the region is possible.
Board: Has the entire layout of Cells, and initializes the fixed ValidationRegions appropriately by passing the appropriate Cells by reference. It also has a solve method that applies Patterns in a pre-defined order until a solution is reached or it is determined that no solution is possible (brute-force pattern must therefore be the last ditch effort).
Pattern: Abstract class that has an apply(Board) method that applies the given pattern to the specified board object (removes possibilities from Cells and sets them when it knows there is only one possibility left). From Sudoku Dragon - Sudoku Strategy, you'll likely implement patterns like OneChoicePattern, SinglePossibilityPattern, OnlySquareRule, etc.
If the question was just "What's an object-oriented design for Sudoku" and you went off and started telling him stuff, he may have been disappointed that you didn't ask for actual requirements. "Sudoku" is pretty broad. Just a data representation? A solver? A means to play? A validator? A puzzle creator?
Until you know what he wanted you to build, you can't really design a solution.
For an Object-Oriented approach to Sudoku I'd do something like this (just using simple names):
A NumberSpace is a single square on the Sudoku board and capable of holding a number from 1-9.
A Block is a grouping of 9 NumberSpaces in a 3x3 pattern, Which would probably just be represented in the class as a multidimensional array of NumberSpace objects. Methods on this could include (bool)validate which would test to make sure no number is repeated per block.
Finally, a Board would represent the entire gaming area where which would be another array (3x3) of Blocks. Methods for this class would include means for verifying the validity of columns/rows.
Two outstanding classes raise from this problem, the main game board and a cell holding a value.
In C#, this would be:
// Main game board
public class BoardGame{
List<List<Cell> cells = new List<List<Cell>>();
public BoardGame(int dimention){
// Initialize and add cells to the cells attribute
}
public bool HorizLineContainsValue(int lineNumber, value){
// return true if any cell in horiz. line number contains value
}
public bool VertLineContainsValue(int lineNumber, value){
// return true if any cell in vertic. line number contains value
}
}
public class Cell {
// X index on the game board
public int X{get; set;}
// Y index on the game board
public int Y{get; set;}
// Value of this cell
public int Value{get; set;}
// Set game board
public GameBoard GameBoard{set;}
public boolean AcceptValue(int value){
// Ask the game board if cells on horizontal line X have this value
// Ask the game board if cells on vertical line Y have this value
// And return true or false accordingly
}
}
If you wish to consider the 3*3 block then you might go for the composite design pattern which will fit this problem very well.
Here is a link to a very interesting and pragmatic book resolving a complex game using OOAD and design patterns
I am not sure about this, but I have a feeling that the interviewer probably wanted something like MVC pattern etc, a high level design/architecture. Then, within this context, you will have three modules/components: model, view and controller. Each of which is then made up of one or more classes. For most interactive applications, this pattern or some variation/related pattern is applicable.
I would say this would have been enough. Since, in an interview you don't have enough time to come up with details of classes, neither it is necessary to do so (at least in typical cases).
I am trying to come up with a Java hand history class for Texas Hold'em and wanted to bounce an idea off here.
Requirements are that every action is stored and there is an efficient way to traverse each HandHistory object (which would represent a single played hand) to match common 'lines' like the standard continuation bet (i.e. the preflop raiser who was in late position preflop and probably is in position postflop is checked to and then makes a 75%ish pot bet).
Ignore for the moment that the definitions for each of the lines is fuzzy at best. As a first stab, I was thinking of organizing it like so:
public class HandHistory {
private Integer handnumber;
//in case we saw things at showdown, put them here
private HashMap<Player,String> playerHands;
private String flopCards;
private String turnCard;
private String riverCard;
private HashMap<BetRound,LinkedHashMap<Integer,ArrayList<PlayerAction>>> actions;
}
So, for each betround we store a linked hashmap whose keys are integers that are the offsets from first position to act for that betround, so preflop UTG is 0.
We generate the actions in position order already, so use a linked hashmap so we can iterate nicely later and skip over positions that are sitting out,etc.
Each arraylist will contain the actions that that position had in that betround. Most of the time this array will have one element, but in cases like, limps and then calls, it will have two.
Can anyone see a better data structure to use for this?
small change, since holdem has a fixed number of betting rounds, maybe
private HashMap<BetRound,LinkedHashMap<Integer,ArrayList<PlayerAction>>> actions;
could just be:
private LinkedHashMap<Integer,ArrayList<PlayerAction>>[] actions= new ... ;
also, here's a couple of books that may be of interest:
http://www.amazon.com/Poker-strategy-Winning-game-theory/dp/0399506691
http://www.amazon.com/Mathematics-Poker-Bill-Chen/dp/1886070253
class Card {
// ??? probably just an int (0 to 51), but certainly not a String.
// Instead of using class Card below, directly using an int woulb be OK.
}
class Hand {
Set<Card> hand; // size 2
}
class Draw { // not sure of the exact poker name for the 5 cards
Set<Card> flop; // size 3
Card turn;
Card river;
}
class Bet {
Player player;
// or maybe "Double" instead; then amount == null means player dropping out.
// or use 0.0 to mean dropped out.
double amount;
}
class BettingRound {
// Includes initial "entry" and all subsequent calls.
// Should include players dropping out also.
List<Bet> bets;
}
class Game {
Draw draw;
Map<Player, Hand> hands;
// rounds 0 and 1 are special since turn and river are not shown
List<BettingRound> rounds;
}
You should also know how much money each player has, I guess. You could keep track of that with a third field (total cash before the bet) in class Bet.
After thinking about it for a bit more, I think I have answered my own question. I've decided not to try to both store every action in a tabular way and try to get quick lookup of frequency counts for betting lines in the same data structure.
Instead, I am going to use my class above as the database-like storage to disk and use a DAG for the betting lines where the edges are tuples of {action, position, players ahead} and the vertices are frequency counts. I think a DAG is correct over a trie here since I do want multiple edges coming into a vertex since lines with common suffix are considered close.