Binary Maze Generator - algorithm

I'm trying to make a simple maze generator using the simplest algorithm I know of.
This is what my code looks like right now but there is almost never a path from start to finish and I don't know what I'm doing wrong. Here is the algorithm page
function generateMaze() {
let cells = []
for (var i=0;i<nodes.length;i++){
let cell = new Cell(nodes[i].x, nodes[i].y)
cells.push(cell)
//obstacles.push([nodes[i].x, nodes[i].y])
}
for (var i=0;i<cells.length;i++){
if (i % 2 == 0){
if (round(random(1, 2)) == 1){
obstacles.push([cells[i].x, cells[i].y-base])
}
else{
obstacles.push([cells[i].x-base, cells[i].y])
}
}
}
}
class Cell{
constructor(x, y){
this.x = x
this.y = y
this.has_visited = false
this.neigbors = []
}
}
Obstacles is just an empty array to hold the walls and base is how big each block is.

Related

How to set up if statements so that loop goes forward and then in reverse? Processing

int x = 31;
int y = 31;
int x_dir = 4;
int y_dir = 0;
void setup ()
{
size (800, 800);
}
void draw ()
{
background (150);
ellipse (x,y,60, 60);
if (x+30>=width)
{
x_dir =-4;
y_dir = 4;
}
if (y+30>=height)
{
x_dir=4;
y_dir = 0;
}
if (x+30>=width)
{
x_dir = -4;
}
x+=x_dir;
y+=y_dir;
println(x,y);
}
Hi,
I have to create this program in processing which produces an animation of a ball going in a Z pattern (top left to top right, diagonal top right to bottom left, and then straight from bottom left to bottom right) which then goes backwards along the same path it came.
While I have the code written out for the forward direction, I don't know what 2 if or else statements I need to write for the program so that based on one condition it goes forwards, and based on another condition it will go backwards, and it will continue doing so until it terminates.
If I am able to figure out which two if statements I need to write, all I need to do is copy and reverse the x_dir and y_dir signs on the forward loop.
There are a ton of different ways you can do this.
One approach is to keep track of which "mode" you're in. You could do this using an int variable that's 0 when you're on the first part of the path, 1 when you're on the second part of the path, etc. Then just use an if statement to decide what to do, how to move the ball, etc.
Here's an example:
int x = 31;
int y = 31;
int mode = 0;
void setup ()
{
size (800, 800);
}
void draw ()
{
background (150);
ellipse (x, y, 60, 60);
if (mode == 0) {
x = x + 4;
if (x+30>=width) {
mode = 1;
}
} else if (mode == 1) {
x = x - 4;
y = y + 4;
if (y+30>=height) {
mode = 2;
}
} else if (mode == 2) {
x = x + 4;
if (x+30>=width) {
mode = 3;
}
} else if (mode == 3) {
x = x - 4;
y = y - 4;
if (y-30 < 0) {
mode = 2;
}
}
}
Like I said, this is only one way to approach the problem, and there are some obvious improvements you could make. For example, you could store the movement speeds and the conditions that change the mode in an array (or better yet, in objects) and get rid of all of the if statements.

Othello Minimax Algorithm

I am trying to implement an artificial intelligence player for Othello using the Minimax algorithm. The computer plays decently, but its not great. Did I implement it correctly in my following code?
Coordinate bestCoordinate = null;
public int minimax(MyButton[][] gameBoard, int depth, boolean maximizingPlayer) {
if (depth == 0) {
return evaluateBoard(gameBoard);
}
if (maximizingPlayer) {
int bestValue = Integer.MIN_VALUE;
LinkedList<Coordinate> moves = generateMoves(gameBoard);
for (Coordinate move : moves) {
MyButton[][] newBoard = cloneBoard(gameBoard);
processMove(newBoard, newBoard[move.getxCoordinate()][move.getyCoordinate()]);
int v = minimax(newBoard, depth - 1, !maximizingPlayer);
if (v > bestValue) {
bestValue = v;
bestCoordinate = move;
}
}
return bestValue;
}
else {
int bestValue = Integer.MAX_VALUE;
LinkedList<Coordinate> moves = generateMoves(gameBoard);
for (Coordinate move : moves) {
MyButton[][] newBoard = cloneBoard(gameBoard);
processMove(newBoard, newBoard[move.getxCoordinate()][move.getyCoordinate()]);
int v = minimax(newBoard, depth - 1, !maximizingPlayer);
if (v < bestValue) {
bestValue = v;
bestCoordinate = move;
}
}
return bestValue;
}
}
Also, here is my evaluation function:
public int evaluateBoard(MyButton[][] gameBoard) {
int blackPieces = 0;
int whitePiecess = 0;
for (MyButton[] array : gameBoard) {
for (MyButton button : array) {
if (button.getBackground().equals(Color.black)) {
blackPieces++;
} else if (button.getBackground().equals(Color.WHITE)) {
whitePiecess++;
}
}
}
int cornerBonus = 10;
if (gameBoard[0][0].getBackground().equals(Color.BLACK)) {
blackPieces += cornerBonus;
}
if (gameBoard[0][getBoardWidth() - 1].getBackground().equals(Color.BLACK)) {
blackPieces += cornerBonus;
}
if (gameBoard[getBoardHeight() - 1][0].getBackground().equals(Color.BLACK)) {
blackPieces += cornerBonus;
}
if (gameBoard[getBoardHeight() - 1][getBoardWidth() - 1].getBackground().equals(Color.BLACK)) {
blackPieces += cornerBonus;
}
if (gameBoard[0][0].getBackground().equals(Color.WHITE)) {
whitePiecess += cornerBonus;
}
if (gameBoard[0][getBoardWidth() - 1].getBackground().equals(Color.WHITE)) {
whitePiecess += cornerBonus;
}
if (gameBoard[getBoardHeight() - 1][0].getBackground().equals(Color.WHITE)) {
whitePiecess += cornerBonus;
}
if (gameBoard[getBoardHeight() - 1][getBoardWidth() - 1].getBackground().equals(Color.WHITE)) {
whitePiecess += cornerBonus;
}
return whitePiecess - blackPieces;
}
(The computer always plays white, and the human is black).
I'm mainly unsure because the computer doesn't seem to protect corners, despite the bonus points that they give. Is there anything wrong with my code/logic?
You are updating your best move at each depth. Make a constant called SEARCH_DEPTH outside of your function that you use every time you call the function and do an if check:
if(depth == SEARCH_DEPTH) {
bestCoordinate = move;
}
Also, assuming you are the maximizing player, you only want to set the move in the if(maximizingPlayer) block.
I did not test your code out myself, but that is the minimax algorithm, and it appears to be written correctly (assuming your helper functions are implemented correctly). I have some points that might give you insight as to why your agent is not acting optimally:
I see your objective function is the number of pieces your agent has minus the number the opponent has, plus a bonus for corner pieces. This might seem like the best strategy, but I would read up on how good Othello players make their moves. Often, they try to flip only one piece if they can until late game, as they have more opportunities that way.
Minimax won't necessarily return the moves that will lead to capturing corners, even if you weigh them highly, because it might be undermined by the opponent's choice of moves. For example, lets say your algorithm looks three turns ahead on the computer's turn, so it first looks at a state where it capture a corner with a high objective function. However, your opponent will be choosing the route that will minimize your objective function, and as such the computer will not view moves moving towards capturing a corner piece as optimal because of the risk. I don't know how easy this will be, but if you can somehow visualize the tree, you might be able to figure out if this is the case.

Generate several random numbers, one of which must be the correct answer to a sum?

I have created a Space Invaders game in which the player must shoot an asteroid which displays a random number. A sum will also be randomly generated at the start of the scene. Once the player shoots an asteroid the scene reloads, with points awarded for correct answers.
The problem I am having is that I need at least one asteroid to display the correct answer. I am currently achieving this by reloading the scene until an asteroids number matches the answer to the sum. This can take quite a few reloads and looks really bad. Is there a better way to achive this which will look better and be more efficient. I have included my effort below. I appreciate any comments. Thanks!
Script for checking the correct answer and reloading the scene.
#pragma strict
function Start ()
{
}
{
if (
Asteroid1_Script.asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid2_Script.asteroid2Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid3_Script.asteroid3Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid4_Script.asteroid4Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid5_Script.asteroid5Value != (Sum_Script.sumA - Sum_Script.sumB)
)
{
Application.LoadLevel("L1");
}
}
Script for randomly generating the sum.
#pragma strict
static var sumA :int = 0;
static var sumB :int = 0;
function Start ()
{
var newSumA = Random.Range(6,10);
sumA = newSumA;
var newSumB = Random.Range(1,6);
sumB = newSumB;
}
function Update () {
//Question Output.
guiText.text = sumA.ToString() + " - " + sumB.ToString()+ " =";
}
Script for generating an asteroids random number.
#pragma strict
var mainCam: Camera;
static var asteroid1Value : int = 0;
var asteroid1 : Transform;
var Asteroid1Style : GUIStyle;
function Start ()
{
var newAsteroid1Value = Random.Range(0,10);
asteroid1Value = newAsteroid1Value;
asteroid1.position.x = mainCam.ScreenToWorldPoint (new Vector3 (160f, 0f, 0f)).x;
asteroid1.position.y = mainCam.ScreenToWorldPoint (new Vector3 (0f, 450f, 0f)).y;
}
function OnGUI()
{
var point = Camera.main.WorldToScreenPoint(transform.position);
GUI.Label(new Rect(point.x, Screen.currentResolution.height - point.y - 530, 110, 100), asteroid1Value.ToString(), Asteroid1Style);
}
function OnCollisionEnter(col : Collision)
{
if(asteroid1Value == (Sum_Script.sumA - Sum_Script.sumB))
{
Destroy(gameObject);
Score_Script.score ++;
}
if(asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB))
{
Score_Script.score --;
}
}
Do as you are doing, generate 5 random numbers for your asteroids.
Then generate a random number between 1 and 5, this is your random asteroid, and then set its value to the answer. (sumA - sumB)
You just need to abstract your logic.
The best argument I can make is, simply put, build your random numbers before you build your asteroids.
That way, you always have a correct one.
I would simply code:
function start(){
var x = 5 //X being whatever number of asteroids you wish.
var a = new Array();
for(var i=0; i<x; i++){
a[i] = Random.Range(0,10);
}
for( i in a){ buildAsteroid(a[i]) }
}
And... if the number matches, success.

Cannot convert from void to PVector in Processing

I'm learning processing and am trying generate fractals using Pascal's triangle. This requires arrays of PVectors. I have run into an issue that I don't understand—I'm getting cannot convert from void to PVector
This is an excerpt, not every variable is defined in the excerpt, but I figure the issue is probably something such that I won't need to reveal more code than this—more code shown might just obfuscate the problem.
arrayCopy(points,old_points);
points = new PVector[int(pow(2, j))];
if (j == 1)
{
points[0] = new PVector(0,0);
}
if (j == 2)
{
points[0] = new PVector(1,0);
points[1] = new PVector(-1,0);
}
else
{
//j will be 3 for the THIRD term in the series
int number_of_terms_to_fill = int(pow(j - 1, 2));
int[] pasc = PascalTriangle(j - 1);
float real = findReal(pasc, x, y, number_of_terms_to_fill);
float imagi = findImagi(pasc, x, y, number_of_terms_to_fill);
PVector v = new PVector(real, imagi);
for (int k = 0; k < number_of_terms_to_fill; k = k + 2)
{
points[k] = old_points[k].add(v); //!!***PROBLEM LINE***!!!
points[k+1] = old_points[k].sub(v);
}
}
My other functions, such as findReal and findImagi, I believe are correct. The addition on the problem line should be an addition between two PVectors—a legal operation. Instead something is void? Perhaps arrayCopy isn't a deep copy like I'd want?
Not sure what is going on.
The method .add() does not return a PVector (it returns nothing, thus void) so you can't do
points[k] = old_points[k].add(v);
I suppose what you are trying to do is add v to old_points[k] and pass it to points[k] which will not work like that... You have to do it like this:
old_points[k].add(v);
points[k] = old_points[k];
old_points[k].sub(v);
points[k+1] = old_points[k];
In order for what you wrote to be valid, the add function should have been like this:
PVector add(PVector v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
}
Instead it looks sort of like this:
void add(PVector v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
}
Edit: After Ryan's comment below, I provide here another way, using the static .add() method which does return a PVector...
points[k] = PVector.add(old_points[k],v);
points[k+1] = PVector.sub(old_points[k],v);

How can I improve Java2D performance of TextLayout.draw(..)

I'm using the Java2D TextLayout class together with a LineBreakMeasurer and an AttributedCharacterIterator to draw a piece of text into a box. The text is wrapped.
Profiling shows me that the code is very slow. Most of the time is lost in the method TextLayout.draw(..).
Does anyone have a suggestion for speed improvement?
// Get iterator for string
AttributedCharacterIterator iterator = attribText.getIterator();
// Create measurer
LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, context);
// loop over the lines
int i = 1;
while (measurer.getPosition() < iterator.getEndIndex()) {
// Get line
TextLayout textLayout = measurer.nextLayout(w);
// get measurements
float ascent = textLayout.getAscent();
float descent = textLayout.getDescent();
float leading = textLayout.getLeading();
float size = ascent + descent;
// Move down to baseline
if( i == 1 ) {
if( coverType == CoverType.SPINE ) {
y = (box.height-size)/2;
y -= (size+leading)*(lines-1)/2;
} else if( vAlign == Alignment.Center ) {
y += (h-size)/2-(size+leading)*(lines-1)/2;
} else if( vAlign == Alignment.Bottom ) {
y += (h-size) - (size+leading)*(lines-1);
}
}
y += ascent;
// calculate starting point for alignment
float paintX = x;
switch( hAlign ) {
case Right: {
paintX = x + w - textLayout.getVisibleAdvance();
break;
}
case Center: {
paintX = x + (w - textLayout.getVisibleAdvance())/2;
break;
}
}
// Draw line
textLayout.draw(g2d, paintX, y);
// Move down to top of next line
y += descent + leading;
i++;
}
The relevant code snippet is shown above. attribText is an AttributtedString set before. context is the g2d.getFontRenderContext().
This post is rather old now so I hope you have found a solution that works for your needs. If you haven't here is something to think about. You only need to draw the text that is within the visible region. Since you know the y coordinate of each line it is easy to check to see if the y lies within the bounds of getVisibleRect(). Only painting the text that is necessary greatly improves performance (assuming of course that your text is longer than a single page).

Resources