1

I am currently working on a C# checkers game for a university project in programming. But i have came to the point where i need to check whether a piece can be moved, or jump, but i feel like i'm using lots of code that isn't necessary to get true or false answers.

if (arrayX == 0)
{
    if (board.GetBoard(arrayX + 1, arrayY - 1).Piece == null)
    {
        return true;
    }
}
else if (arrayX == 7)
{
    if (board.GetBoard(arrayX - 1, arrayY - 1).Piece == null)
    {
        return true;
    }
}

For example, is there a more efficient way of doing these if statements? In the code i have more if statements branching off other if statements. So in summary, is there a way you can check loads of parameters, efficiently, without using loads of if statements branching off of one another?

1
  • You can use a loop for (int i = 0; i < ARRAY_LENGTH; i++) { if (bouard.GetBoard( arrayX-1, arrayY-1).Piece == null) Commented Feb 9, 2015 at 23:30

3 Answers 3

3

You may start by creating a method inside the Board class which makes your code slightly shorter:

public class Board()
{
    public bool IsPieceMissing(x, y)
    {
        return this.GetBoard(x, y).Piece == null;
    }
}

...

if (arrayX == 0)
{
    if (board.IsPieceMissing(arrayX + 1, arrayY - 1))
    {
        return true;
    }
}
else if (arrayX == 7)
{
    if (board.IsPieceMissing(arrayX - 1, arrayY - 1))
    {
        return true;
    }
}

The next thing is to work on the business logic, but for that, you need to provide a more global picture. What is the complete body of the method? Is it returning false at the end? Assuming it contains only the part you already provided and the return false; at the end, like this:

private bool DoSomething(arrayX, arrayY)
{
    if (arrayX == 0)
    {
        if (board.IsPieceMissing(arrayX + 1, arrayY - 1))
        {
            return true;
        }
    }
    else if (arrayX == 7)
    {
        if (board.IsPieceMissing(arrayX - 1, arrayY - 1))
        {
            return true;
        }
    }

    return false;
}

you can return immediately instead of waiting until the end. The method becomes:

private bool DoSomething(arrayX, arrayY)
{
    if (arrayX == 0)
    {
        return board.IsPieceMissing(arrayX + 1, arrayY - 1);
    }
    else if (arrayX == 7)
    {
        return board.IsPieceMissing(arrayX - 1, arrayY - 1);
    }

    return false;
}

Since the first condition now returns something anyway, you don't need the else:

private bool DoSomething(arrayX, arrayY)
{
    if (arrayX == 0)
    {
        return board.IsPieceMissing(arrayX + 1, arrayY - 1);
    }

    if (arrayX == 7)
    {
        return board.IsPieceMissing(arrayX - 1, arrayY - 1);
    }

    return false;
}
3
  • Thats been useful, was able to simplify my code massively! Is there any way i can shorten if statements like; if piece can be moved/// if piece is owned by player/// if piece can jump /// if piece something else /// and so on... any way i could do this more efficiently, or is that the best way in general to do it? /// means if statement branching off the one before... if that makes sense? Commented Feb 10, 2015 at 0:21
  • @iBaconButty: as I previously said, without too much code, it's difficult to tell. Also, if your code works but you want to make it better, I would suggest posting it on CodeReview.SE. Commented Feb 10, 2015 at 0:42
  • @iBaconButty you could combine the if statements, or create a method with a meaningful name instead for the if, something like IsOnHorizontalEdge(int arrayX). This would simplify your code even further.
    – Rob Tillie
    Commented Feb 10, 2015 at 9:34
1

I looked at your code and it does not seem to me that it can be simplified in the sense of reducing the total number of lines. It could be made less verbose if you got rid of some of the unnecessary, annoying curly brackets, but I suppose if you liked that idea you would have already done it:

        if (arrayX == 0)
        {
            if (board.GetBoard(arrayX + 1, arrayY - 1).Piece == null)
                return true;
        }
        else if (arrayX == 7)
        {
            if (board.GetBoard(arrayX - 1, arrayY - 1).Piece == null)
                return true;
        }

However, there is one thing that you could try and see if it would simplify your code: define an immutable struct to hold a point.

struct Point
{
    readonly int x; //these are 32-bit, so the entire struct will fit inside a
    readonly int y; //   machine word in a 64-bit architecture.
    Point( int x, int y )
    { 
        Assert( x >= 0 && x < 7 );  
        Assert( y >= 0 && y < 7 ); 
        this.x = x;  
        this.y = y; 
    }
    Point left { get { Assert( x >= 0 );  return new Point( x - 1, y ); } }
    Point right { get { Assert( x <= 7 );  return new Point( x + 1, y ); } }
    bool isLeftmost { get { return x == 0; } }
    bool isRightmost { get { return x == 7; } }
    ...
}

then, you will be able to add cool things to your structure, like this:

    IEnumerable<Point> EnumerateSurrounding()
    {
        for( int dx = -1;  dx <= 1;  dx++ )
        {
            for( int dy = -1;  dy <= 1;  dy++ )
            {
                int xx = x + dx; 
                int yy = y + dy;
                if( xx < 0 || xx > 7 )
                     continue;
                if( yy < 0 || yy > 7 )
                     continue;
                if( xx == 0 && yy == 0 )
                     continue;
                yield return new Point( xx, xy );
            }
        }
    }

So, you will be able to visit all cells surrounding a given cell like this:

foreach( Point p in mypoint.EnumerateSurrounding() )
{
    //do something with p here
}

Disclaimer: I just typed all of the above code, so it is bound to have syntax errors, and perhaps even logical errors. Do not rely on it blindly, read it carefully and use your judgement.

7
  • I never really thought about using pointers and doing it like that... thats actually a really interesting way around it.. i might just try it :) Thanks Commented Feb 10, 2015 at 0:25
  • You sure that will fit in a 64-bit word? I'm not precisely certain how values are stored on the stack, but I suspect they hold type information - at least a pointer to the type record either on the heap or in an assembly table - so while your 2 ints are likely stored in a single word (not certain again as I understand usually everything is word aligned, don't know if this is the case on the stack also), I doubt the whole structure fits in a single word. It's still an efficient structure sure, guess I'm curious if you can back up that claim you made in comments? (I can't refute it off hand) Commented Feb 10, 2015 at 1:56
  • Point as an immutable struct is a classic and absolutely correct usage of structs though, I definitely agree with what you're suggesting here +1 Commented Feb 10, 2015 at 1:57
  • @JimmyHoffa I am quite sure that nothing is held other than the 32 bits of the int. Type information etc come into play only if the individual int gets boxed. If I am wrong about my assumption that the struct fits in 64 bits it will be due to other reasons, for example the hardware may require 64 bit alignment, so the ints may be placed 64 bits apart, thus the structure would need a total of 64+32 bits. I would hope that the CLR has some way of taking care of this problem, but I do not know for sure, and it would be hard for me to check right now.
    – Mike Nakis
    Commented Feb 10, 2015 at 8:27
  • 1
    @MikeNakis ah I didn't think about that, since their type is known at compile time the type information is encoded into the instruction pointers that operate with them, that makes sense. Obviously everything on the heap has type information, but I can see how stack types won't need that, that's very cool! Commented Feb 10, 2015 at 16:26
0

It looks like you are testing edge cases. You can often cut way down on the edge case testing by removing the edges from the problem. Instead of the 8x8 board of checkers, internally make the board 12x12. (Note that this would be easier in a language like Pascal that permits non-standard array bounds.) Now you don't have to worry about most edge case testing--there's enough space out there that the destination of any possible move exists. You still need to reject moves that would go off the edge of the board but even this can be done with a single statement (have an array of good and bad squares, if the prospect cell is a bad cell reject the move.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.